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的回答应该能让它起作用。但不确定是否会更快