python csv嗅探器在windows和linux中的不同行为

python csv嗅探器在windows和linux中的不同行为,python,csv,sniffer,Python,Csv,Sniffer,在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 wi

在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
分隔符应该是“;”我知道有很多逗号、分号和引号字符会让嗅探器感到困惑,但是在windows上用python 3.6运行这段代码时,它工作得非常好。在Linux上运行它(也用python 3.6)总是会引发csv.Error(在其他具有相同分隔符和引号字符的csv文件上也是如此)。我用read(1024)、其他值和readline尝试过,但总是得到相同的结果


对这种不同行为有何解释?

windows和linux之间默认的记录结束分隔符不同。通常,记录将以CR-LF“对终止“在windows上,而在*nix上,单个LF是标准。在这种情况下,您的嗅探器可能会在windows模式下自行修复,并且需要帮助确定实际的行终止符应该是什么


从外观上看,sniffer默认为
/r/n
,我认为这是windows风格的。它应该能够处理备用的线路终端,但也许有什么东西是被迫的。如果数据文件中的记录长度超过1024,或者没有足够的时间对行终止符进行采样以正确猜测格式,这可能与此有关

windows和linux的默认记录结束分隔符不同。通常,在windows上,记录将以CR-LF“对”终止,而在*nix上,通常使用单个LF。在这种情况下,您的嗅探器可能会在windows模式下自行修复,并且需要帮助确定实际的行终止符应该是什么


从外观上看,sniffer默认为
/r/n
,我认为这是windows风格的。它应该能够处理备用的线路终端,但也许有什么东西是被迫的。如果数据文件中的记录长度超过1024,或者没有足够的时间对行终止符进行采样以正确猜测格式,这可能与此有关

终于找到了这个错误的原因。它与换行符结尾无关。我正在使用Python 3.6.4,并且发现csv.py在这个版本中有一个bug:第220行的正则表达式说:

r'(?P<delim>>[^\w\n"\'])(?P<space> ?)(?P<quote>["\']).*?(?P=quote)(?:$|\n)',  # ,".*?"
r'(?P>[^\w\n“\'])(?P?(?P[“\']).*(?P=quote)(?:$\n),#,*?”
但它应该是:

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

从python 3.6.5开始。该错误似乎已修复

最终找到了导致此错误的原因。它与换行符结尾无关。我正在使用Python 3.6.4,并且发现csv.py在这个版本中有一个bug:第220行的正则表达式说:

r'(?P<delim>>[^\w\n"\'])(?P<space> ?)(?P<quote>["\']).*?(?P=quote)(?:$|\n)',  # ,".*?"
r'(?P>[^\w\n“\'])(?P?(?P[“\']).*(?P=quote)(?:$\n),#,*?”
但它应该是:

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

从python 3.6.5开始。该错误似乎已修复

根据您的建议,我将open(路径名'r',encoding='utf-8')更改为open(路径名'r',encoding='utf-8',换行符=''),并且不再引发错误。然而,windows和linux之间的嗅探器行为似乎仍然存在差异,因为现在,示例文件(我在问题的第一行给出了它)在linux中被识别为单列文件,而windows正确地识别为3列文件。嗅探器可以在windows和linux中正确识别其他不太复杂的文件。因此,请尝试
open(路径名'r',encoding='utf-8',newline='\n')
open(路径名'r',encoding='utf-8',newline='\r\n')
文件是否完全相同?还是复制品?有时,在操作系统之间移动文件可能会导致文件更改(某些传输程序在这方面是“有用的”,并且在复制文件时会损坏文件)但在我看来,正是这种跨unix/windows约定的CRLF与LF的差异造成了这里的悲哀。我已经深入研究了csv嗅探,并可以看到以下行为:…使用“换行符”打开文件”在中,该语句避免了linux中的错误,但在windows和linux中都无法正确检测分隔符,并将其视为单列。在linux和windows中,在没有“换行符”的情况下打开并使用调试器查看“sample”变量的内容时,行之间用\n分隔。嗅探器在windows和linux中接收相同的数据,但csv使用的正则表达式。嗅探器的反应因操作系统而异。。。在windows中,可以找到分隔符和引号的匹配项,在linux中,无论出于何种原因,都找不到匹配项。最近,我一直在windows和*nix系统中使用csv.writer。我遇到的最佳解决方案要求用户知道您的输入是为什么操作系统生成的。例如,行尾字符是什么,可以是/n或r/n/并且按照您的建议使用newline=”“指定。示例:我的输入是在*nix系统上创建的。当相同的代码在Windows上的同一个文件上运行时,我的输出中添加了一个额外的行尾字符-在输出之间留下令人讨厌的空白行*nix系统没有相同的输出问题。根据您的建议,我将open(路径名'r',encoding='utf-8')更改为open(路径名'r',encoding='utf-8',newline=''),并且不再引发错误。然而,windows和linux之间的嗅探器行为似乎仍然存在差异,因为现在,示例文件(我在问题的第一行给出了它)在linux中被识别为单列文件,而windows正确地识别为3列文件。在windows和linux中,嗅探器可以正确识别其他不太复杂的文件。因此,请尝试
open(路径名'r',enc