Python 3.x 如何加速下面的python3代码?
所以我试图解析一个巨大的文件,下面的代码解析起来太长了。文件大小为2gb。我希望有人能帮我加快速度Python 3.x 如何加速下面的python3代码?,python-3.x,Python 3.x,所以我试图解析一个巨大的文件,下面的代码解析起来太长了。文件大小为2gb。我希望有人能帮我加快速度 import os, shlex def extractLinkField(inDir, outDir): fileList = os.listdir(inDir) links = set() for File in fileList: print(File) with open(os.path.join(inDir, File), en
import os, shlex
def extractLinkField(inDir, outDir):
fileList = os.listdir(inDir)
links = set()
for File in fileList:
print(File)
with open(os.path.join(inDir, File), encoding="utf8") as inFile:
for line in inFile:
try:
links.add(shlex.split(line)[2])
except Exception:
continue
outFile = open(os.path.join(outDir, 'extractedLinks.txt'), 'a+', encoding="utf8")
for link in list(links):
outFile.write(link + '\n')
outFile.close()
Path = os.path.join(os.getcwd(), 'logs')
extractLinkField(Path, os.getcwd())
文件格式如下:
90 "m z pd gk y xr vo" "n l v ogtc dj wzb" "d zi pfgyo b tmhek" "df qu venr ls hzw j"
82 "p wgd lv f kt eb uq" " ij cw v a r y qp" " pf qdlcgm jz os y" "f xm n cr ublzig"
89 "c pgib a ost whk" "ria m h fvcb es z" "qzoy g xbr makc" "ms lqc v ektb w "
66 "zxm pe hb vi dj " "rg ebfwp y zv oakm" "b nut ko je m crsh" " imsxtzfw g ka j l "
2 "uyhnpt l dj qak " "o hned j pqub t a " "v hlyc afwi sgr p" "h wtvi g o nc sujqx"
17 "apo ufliz qctbd xh " "k lxgbrcwzf mnhtq p" "z gk m rsbu l" " ds m au w cior "
9 " h t ac jpn ok mz" "aty rs w box vk zefp" "nm fbc x egt zruap " "xg oi j z wyf v dqp"
82 "xs q ve k oi c " " z lfa dwiprxb ku g" "kua p f b oqz jrt " " t wlvy d po qrx e"
51 "cx iq wuvhb gkmo y" " u p yx bv mjz r" "oatc wuxd yfgjs ri " "vbg w h ife myl"
91 "cdqkp rn u ow h f" "ko rt y c eis d q jl" " lv fe r zpju yw " " wz vtxa jn lg s"
83 "bts dl kjycre ozv " " k i q m r ypsu lh " "pr exw sznqa yvu i " " uq tzk nomrx e "
请注意,由引号包装的文件中的字符串不应拆分,必须作为一个整体进行解析(仍然包装在引号中)
罪魁祸首显然是shlex.split()。这是一个相当昂贵的操作(为每个拆分创建一个全新的对象,其中包含大量的样板文件),因此如果您的数据遵循所提供的格式,您可以尝试手动解析数据 因此,这里有一个方法,它对示例数据的执行方式与
shlex.split()
相同:
因此,速度要快12倍多。但我们可以做得更好。。。这种方法的问题在于,它在Python端有大量缓慢的str.find()
调用(尽管逐字执行会更慢)和字符串洗牌,因此快速的C端没有机会发挥其魔力。如果您要在C中实现这一点(进行一些优化)并将其作为一个模块加载,速度会非常快,但遗憾的是
因此,我认为,regex
可能会更快,因为它主要在C端执行,即使您给它更复杂的规则,它也应该能够在足够大的数据上优于纯Python字符串搜索和操作。因此,下一位候选人:
import re
FIELDS_PATTERN = re.compile(r"(?:\"(.*?)\"|(\S+))")
def regex_split(data):
return [x[0] or x[1] for x in FIELDS_PATTERN.findall(data)]
现在我们有了最终的基准:
shlex.split: 10,000 loops: 11.51 s, per loop: 1.151 ms
manual_split: 10,000 loops: 0.951 s, per loop: 95.11 µs
regex_split: 10,000 loops: 0.482 s, per loop: 48.16 µs
是的,regex one几乎比shlex.split()快24倍。!它们都会为您的测试数据生成相同的分割结果
但是在您跳入和跳出shlex
之前,您需要彻底测试这两种类型,以确保它们适合您的数据-例如,它们无法识别转义引号或特殊的POSIX拆引号字符串,因此,如果您的数据中存在此类情况,您必须将其考虑在内
此外,如果您想提高一点点速度,请立即写入输出,而不是存储在一个集合中,以便稍后循环:
with open(os.path.join(out_dir, 'extractedLinks.txt'), 'a+', encoding="utf8") as out_file:
links = set() # temp store to ensure uniqueness...
for current_file in file_list:
with open(os.path.join(in_dir, current_file), encoding="utf8") as in_file:
for line in in_file:
try:
link = shlex.split(line)[2] # or whatever other function
if link not in links:
links.add(link)
out_file.write(link + "\n")
except Exception:
continue
假设你将在你庞大的输入文件中收集数百万行,这可能会缩短一两秒钟…如果你打算否决我的问题,请解释你为什么这么做。谢谢。你能不能把你要解析的文件的10行写进去,这样我就可以给你写一个快速的熊猫解析器?是的,我现在就做@MattI已经把它添加到了帖子中@Matt谢谢你的帮助。除了在拆分时忽略带引号的字符串之外,还有其他要求吗?回答得好,我本来打算投一个熊猫版的,但你的基准测试似乎否定了这个需求哇:哦,真是让人大吃一惊。谢谢你提供这么多细节。我从你的回答中学到了很多。
shlex.split: 10,000 loops: 11.51 s, per loop: 1.151 ms
manual_split: 10,000 loops: 0.951 s, per loop: 95.11 µs
regex_split: 10,000 loops: 0.482 s, per loop: 48.16 µs
with open(os.path.join(out_dir, 'extractedLinks.txt'), 'a+', encoding="utf8") as out_file:
links = set() # temp store to ensure uniqueness...
for current_file in file_list:
with open(os.path.join(in_dir, current_file), encoding="utf8") as in_file:
for line in in_file:
try:
link = shlex.split(line)[2] # or whatever other function
if link not in links:
links.add(link)
out_file.write(link + "\n")
except Exception:
continue