【发布时间】:2020-06-29 06:55:19
【问题描述】:
我有一个相当大的 python 包,它与第三方 API 服务器同步交互,并与服务器执行各种操作。此外,我现在还开始通过腌制 JSON 响应来收集一些数据以供将来分析。在分析了几个序列化/数据库方法之后,在我的情况下使用 pickle 是最快的。我的基本伪代码是:
While True:
do_existing_api_stuff()...
# additional data pickling
data = {'info': []} # there are multiple keys in real version!
if pickle_file_exists:
data = unpickle_file()
data['info'].append(new_data)
pickle_data(data)
if len(data['info']) >= 100: # file size limited for read/write speed
create_new_pickle_file()
# intensive section...
# move files from "wip" (Work In Progress) dir to "complete"
if number_of_pickle_files >= 100:
compress_pickle_files() # with lzma
move_compressed_files_to_another_dir()
我的主要问题是文件的压缩和移动需要几秒钟才能完成,因此减慢了我的主循环。在不对现有代码进行任何重大修改的情况下以非阻塞方式调用这些函数的最简单方法是什么?我不需要函数的任何返回,但是如果任何失败都会引发错误。另一个“很高兴”是 pickle.dump() 也是非阻塞的。同样,我对“它是否引发错误?”之外的返回不感兴趣。我知道 unpickle/append/re-pickle 每个循环并不是特别有效,但是它确实避免了当 api 由于连接问题、服务器错误等而退出时数据丢失。
我对线程、多处理、异步等方面的知识为零,经过大量搜索,我现在比两天前更困惑!
仅供参考,所有与文件相关的函数都在一个单独的模块/类中,因此可以在必要时进行异步处理。
编辑: 可能会多次调用上述函数,所以我想需要某种排队?
【问题讨论】:
-
最简单的解决方案可能是
threading标准库包。这将允许您在主循环继续时生成线程来进行酸洗。但是,如果您已经将磁盘 i/o 最大化,这实际上不会使整个程序更快。您最终会提前完成主循环,并将数据缓冲在内存中,直到磁盘操作完成。话虽如此,在您现有的循环中几乎可以肯定有相当多的“死时间”等待 API 响应,因此您可以获得相当多的收益。 -
@SimonN 是 Pickle 线程安全的吗? API 经常等待服务器响应,但是密集的东西会阻塞循环并不必要地减少 API 请求。
-
这个有点笼统,Python中线程/异步编程的资源不是已经很多了吗?
-
@Birchy:不要将酸洗放在线程中(无论如何,这可能是您运行时的一个微不足道的部分)。 LZMA 压缩需要永远并且可以在后台线程中运行就好了。
-
我认为你应该检查一下它可能对你有帮助:stackoverflow.com/questions/52786328/…
标签: python linux asynchronous pickle