Python 如何使用aiofiles异步pickle大量文件?
我想写一个列表,Python 如何使用aiofiles异步pickle大量文件?,python,async-await,dill,python-aiofiles,Python,Async Await,Dill,Python Aiofiles,我想写一个列表,数据,每个项目一个文件,如下所示: for i,chunk in enumerate(data): fname = ROOT / f'{i}.in' with open(fname, "wb") as fout: dill.dump(chunk, fout) 由于数据列表可能相当长,而且我正在向网络存储位置写入数据,因此我花费了大量时间在NFS中来回等待迭代,如果可能的话,我希望异步执行此操作 我现在有一些东西基本上是这样的: import di
数据
,每个项目一个文件,如下所示:
for i,chunk in enumerate(data):
fname = ROOT / f'{i}.in'
with open(fname, "wb") as fout:
dill.dump(chunk, fout)
由于数据列表可能相当长,而且我正在向网络存储位置写入数据,因此我花费了大量时间在NFS中来回等待迭代,如果可能的话,我希望异步执行此操作
我现在有一些东西基本上是这样的:
import dill
import asyncio
import aiofiles
from pathlib import Path
ROOT = Path("/tmp/")
data = [str(i) for i in range(500)]
def serialize(data):
"""
Write my data out in serial
"""
for i,chunk in enumerate(data):
fname = ROOT / f'{i}.in'
print(fname)
with open(fname, "wb") as fout:
dill.dump(chunk, fout)
def aserialize(data):
"""
Same as above, but writes my data out asynchronously
"""
fnames = [ROOT / f'{i}.in' for i in range(len(data))]
chunks = data
async def write_file(i):
fname = fnames[i]
chunk = chunks[i]
print(fname)
async with aiofiles.open(fname, "wb") as fout:
print(f"written: {i}")
dill.dump(chunk, fout)
await fout.flush()
loop = asyncio.get_event_loop()
loop.run_until_complete(asyncio.gather(*[write_file(i) for i in range(len(data))]))
现在,当我测试写操作时,这看起来足够快,在我的NFS上是值得的:
# test 1
start = datetime.utcnow()
serialize(data)
end = datetime.utcnow()
print(end - start)
# >>> 0:02:04.204681
# test 3
start = datetime.utcnow()
aserialize(data)
end = datetime.utcnow()
print(end - start)
# >>> 0:00:27.048893
# faster is better.
但当我实际/反/序列化我编写的数据时,我发现它可能很快,因为它没有写入任何内容:
def deserialize(dat):
tmp = []
for i in range(len(dat)):
fname = ROOT / f'{i}.in'
with open(fname, "rb") as fin:
fo = dill.load(fin)
tmp.append(fo)
return tmp
serialize(data)
d2 = deserialize(data)
d2 == data
# True
好,鉴于:
aserialize(data)
d3 = deserialize(data)
>>> Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 6, in deserialize
File "...python3.7/site-packages/dill/_dill.py", line 305, in load
obj = pik.load()
EOFError: Ran out of input
aserialize(数据)
d3=反序列化(数据)
>>>回溯(最近一次呼叫最后一次):
文件“”,第1行,在
文件“”,第6行,反序列化
文件“…python3.7/site packages/dill/_dill.py”,第305行,已加载
obj=pik.load()
EOFError:输入不足
也就是说,异步写入的文件是空的。难怪这么快
我如何异步地将我的列表放入文件中,并让它们实际写入?我想我得等着你把我甩了?我原以为fout.flush可以处理这个问题,但似乎不行。我将行
dill.dump(chunk,fout)
改为wait fout.write(dill.dumps(chunk))
并将数据写入文件并正确反序列化。似乎dill.dump
仅适用于常规同步文件调用file.write
方法,而不使用await
关键字。这些方法等效吗?我在看:我不清楚f.write(dill.dumps(x))==dill.dump(x,f)
@Mittenchops,正如您所看到的,dumps
使用dump
将数据写入StringIO
对象,其行为类似于内存文件()。因此,它的内容应该与写入常规文件的内容相同。这意味着必须等待f.write()
。dill library对此一无所知,认为您传递的fin
是一个常规文件。您应该得到“RuntimeWarning:从未等待协同程序”@sanyash的回答应该能让它起作用。但不确定是否会更快