这是我的情况:我需要在一个群集上运行300个进程(它们是独立的),并将所有部分数据全部添加到同一DataFrame中(它们还需要在读取文件之前结果写作)。他们可能需要在整个运行时多次执行此操作。
因此,我尝试通过portalocker
包使用写锁定文件。但是,我遇到了一种错误,我不知道它从哪里来。
这是每个程序将在其中写入同一文件的基本代码:
with portalocker.Lock('/path/to/file.pickle', 'rb+', timeout=120) as file:
file.seek(0)
df = pd.read_pickle(file)
# ADD A ROW TO THE DATAFRAME
# The following part might not be great,
# I'm trying to remove the old contents of the file first so I overwrite
# and not append, not sure if this is required or if there's
# a better way to do this.
file.seek(0)
file.truncate()
df.to_pickle(file)
以上大部分时间都是有效的。但是,我拥有写锁定的同步进程越多,在pd.read_pickle(file)
阶段得到的EOFError错误就越多。
EOFError: Ran out of input
回溯很长而且很复杂。
无论如何,到目前为止,我的想法是由于上面的代码有时可以工作,所以上面的代码必须*(尽管它可能很凌乱,而且我不介意听到做同一件事的更好方法)。
但是,当我有太多尝试写锁定的进程时,我怀疑该文件没有节省时间或什么原因,或者至少在某种程度上,下一个进程还看不到该文件已保存的内容。之前的过程。
有办法解决吗?我尝试在代码周围添加time.sleep(0.5)
语句(在read_pickle
之前,在to_pickle
之后),但我不认为这会有所帮助。有谁了解可能发生的事情或知道更好的方法吗?
还请注意,我认为写锁定不会超时。我尝试对过程进行计时,并且还在其中添加了一个标志,以在写锁超时时进行标志。虽然有300个进程,并且它们可能会尝试以不同的速率进行写入,但总的来说,我估计每秒大约有2.5次写入,这似乎不应该使系统过载?*
*腌制的DataFrame的大小为几百KB。
答案 0 :(得分:0)
也许这是一个模糊的问题,但是由于我设法解决了这个问题并更好地了解了情况,所以我认为将我发现的内容发布在这里是有益的,希望其他人也可以找到。在我看来,这是一个可能也可能会引起其他问题的问题。
请登录“ portalocker” github页面获取帮助和答案:https://github.com/WoLpH/portalocker/issues/40
问题似乎是我在集群上执行此操作。结果,文件系统有点复杂,因为进程在多个节点上运行。保存的文件“同步”并在不同的运行进程中看到的时间可能比预期的长。
对我来说似乎起作用的是刷新文件并强制系统同步,此外(尚不确定是否可选),之后再添加更长的“ time.sleep()”。
根据“ portalocker”开发人员的说法,文件在集群上同步可能花费无法预测的时间,因此您可能需要更改睡眠时间。
换句话说,在保存文件后添加它:
df.to_pickle(file)
file.flush()
os.fsync(file.fileno())
time.sleep(1)
希望这可以帮助其他人。