Python 3.6.3对2.7.3正则表达式:相同的脚本不同的结果

时间:2018-01-25 11:25:53

标签: python regex python-3.x python-2.7

我正在使用Python版本3.6.3和2.7.3运行相同的脚本。该脚本在2.7.3中工作正常,但在3.6.3中没有。似乎区别在于我的代码的正则表达式部分。

我在两个脚本版本的同一个外部文件中搜索一些字符串,保存列表中的匹配。结果列表的len()对于两个版本是不同的。

我尝试通过创建一个用于正则表达式的小文件来创建一个重现错误的MWE,但是两个版本的Python都会生成相同的输出。我唯一的解决方案是提供原始文件。但这是一个很长的文本文件,因此您可以从此处下载:https://ufile.io/jjc56此文件可用30天。我想也许这比将一切都粘贴到问题上要好。

这段代码重现了错误。

import re

inputfile = "opt-guess-firsttetint-r-h2o.out"
with open(inputfile,"r") as input_file:
    input_string = input_file.read()
    input_file.close()

match_geometry = list(re.findall('CARTESIAN COORDINATES \(ANGSTROEM\)(.*?)CARTESIAN COORDINATES \(A\.U\.\)', input_string, re.DOTALL))

match_energy = list(re.findall('FINAL SINGLE POINT ENERGY(.*?)-------------------------', input_string, re.DOTALL))

print(len(match_geometry))
print(len(match_energy))

使用Python 3.6.3输出:

78
77

使用Python 2.7.3输出:

188
188

进行比较:

$ grep "CARTESIAN COORDINATES (ANGSTROEM)" externalfile | wc -l
> 188

$ grep "FINAL SINGLE POINT ENERGY" externalfile | wc -l
> 188

如果您需要更多信息,请说出来!

1 个答案:

答案 0 :(得分:2)

Python 2和Python 3之间的主要区别在于文本处理:在Python 2中,文本被视为在裸C中,即一个字节序列碰巧匹配32-128范围内的ASCII字符,这不是真的对于Python 3 - 假定文件中的字节采用某种文本编码,并在程序中处理之前解码为正确的unicode字符点。

同样,在Python2中,regexp默认在“字符串”上运行,而在Python 3上运行在文本字符串上(在Python 2中,如果表达式和文本都是'unicode'对象,则可以使用文本,而不是比'str')

我们需要更多的上下文,但你的问题可能在于Python 3读取你的文本文件,假设编码不正确 - 比如,你的数据是utf-8,但Python假设它是拉丁文1 - 它会读取字符超出ASCII范围不正确,没有给你一个错误,因为0-255的所有字节都是有效的Latin-1 - 但是由此产生的mojibake会使regexp失败。

在阅读您的数据时,只需强行使用encoding="..."来匹配您的文件,您就可以了。

仅供参考,一个可以触发上述行为的角色是“Å” - 在这种特殊情况下我不会发现这种情况。