Python CSV Sniffer различное поведение в Windows и Linux - PullRequest
0 голосов
/ 09 ноября 2018

В приложении wxpython я использую следующий код для определения «диалекта» файла CSV:

pathname = dlg.GetPath()
try:
    self.file = open(pathname, 'r', encoding='utf-8')
except IOError:
    wx.LogError("Cannot open file '%s'." % ntpath.basename(self.file.name))
    return

# check for file format with sniffer
sample = self.file.read(1024)
try:
    dialect = csv.Sniffer().sniff(sample)
except UnicodeDecodeError:
    wx.LogError("Cannot decode file '%s'." % ntpath.basename(self.file.name))
    return
except csv.Error:
    wx.LogError("Cannot determine dialect of '%s'." % ntpath.basename(self.file.name))
    return

Первые строки файла CSV, на котором я использую это:

t;3.1.A.;"UN ECE R51; Sound levels"
;;Is covered by the type approval of the vehicle stage 1, refer to Annex S.
t;3.2.A.;"715/2007/EC; Emissions light duty vehicles Euro 6"
;;Is covered by the type approval of the vehicle stage 1, refer to Annex S.
t;3.3.A.;"UN ECE R34; Fuel tanks"
;;Is covered by the type approval of the vehicle stage 1.
t;3.16.A.;"UN ECE R26; Exterior projections"
;3.16.A.1.;Test and inspections

Разделитель должен быть ';' и кавычка char '"' Мне известно, что есть много запятых, точек с запятой и кавычек, чтобы запутать сниффер, но при запуске этого кода с python 3.6 на windows он отлично работает. Запуск его на Linux (также с python 3.6 ) неизменно вызывает ошибку csv.Error (также в других файлах csv с теми же разделителями и символами кавычек). Я пробовал это с read (1024), с другими значениями, а также с readline, но всегда получаю одинаковые результаты.

Есть какое-нибудь объяснение этому другому поведению?

Ответы [ 2 ]

0 голосов
/ 11 ноября 2018

Наконец-то нашли причину этой ошибки. Это не связано с окончаниями новой строки. Я использую Python 3.6.4 и обнаружил, что в этой версии csv.py есть ошибка: регулярное выражение в строке 220 говорит:

r'(?P<delim>>[^\w\n"\'])(?P<space> ?)(?P<quote>["\']).*?(?P=quote)(?:$|\n)',  # ,".*?"

но должно быть:

r'(?P<delim>[^\w\n"\'])(?P<space> ?)(?P<quote>["\']).*?(?P=quote)(?:$|\n)',  # ,".*?"

от python 3.6.5. ошибка вроде исправлена ​​

0 голосов
/ 09 ноября 2018

Разделитель конца записи по умолчанию отличается в Windows и Linux. Обычно записи завершаются парой CR-LF в окнах, в то время как в * nix единичный LF является нормой. Это может быть тот случай, когда ваш сниффер исправляет себя в режиме windows и нуждается в помощи в определении того, каким должен быть настоящий терминатор строки.

Из документов кажется, что по умолчанию сниффер имеет значение /r/n, которое, как мне кажется, работает на Windows. Он должен справляться с альтернативными ограничителями строки, но, возможно, что-то где-то форсируется. Если длина записей в вашем файле данных превышает 1024, или для выборки с ограничителем строки недостаточно времени, чтобы правильно угадать формат, это может быть связано с этим.

...