【发布时间】:2021-01-31 04:12:11
【问题描述】:
我有一个工作代码,但不确定这是正确的方法。我有两个函数,都发出一个可能需要 1 到 5 秒之间任意时间的 API 请求,但两者都旨在返回相同的输出。我想同时运行这两个,一旦更快的完成它的工作,终止另一个并丢弃它会返回的任何东西。
p1 = Process(target = search1, args=(name) )
p2 = Process(target = search2, args=(name) )
if __name__=='__main__':
p1.start()
p2.start()
while p1.is_alive() and p2.is_alive():
time.sleep(0.2)
if not p1.is_alive():
p2.terminate()
if not p2.is_alive():
p1.terminate()
如果我不等待一段时间(在这种情况下为 0.2 秒),有时如果两者花费的时间相同,则两者都会返回。我测试了很多次并且它有效,但这是正确的方法吗?这种方法是否会出现任何问题?
--- ti7 建议
在 ti7 的建议下尝试使用线程,现在它可以使用线程而不是进程。
def search1(Q_result, name):
result = somefunction()
Q_result.put(result)
def search2(Q_result, name):
time.sleep(10)
result = somefunction()
Q_result.put(result )
import Queue as queue
import threading
Q_result = queue.Queue() # create a Queue to hold the result(s)
if __name__=='__main__':
t1 = threading.Thread(
target=search1,
args=(Q_result, name),
)
t1.daemon = True
t1.start()
t2 = threading.Thread(
target=search2,
args=(Q_result),
)
t2.daemon = True
t2.start()
print(Q_result.get())
【问题讨论】:
-
你有很多这样的任务要做吗?因为对于数千个任务来说,启动和终止进程需要相当多的时间和资源。此外,如果它只是一个 API 请求,那么您可能可以使用与
threading模块中的轻量级线程相同的方法。但总的来说,您的方法还不错,是解决任务的一种方法。但是从某种意义上说,您的解决方案很好,因为它可以清除所有资源,因为当进程被杀死时,所有资源都会被释放。但是如果你使用线程,那么一些资源可能会被泄露。 -
我还有一个想法 - 如果您必须执行许多任务、许多请求,并且您的下一个请求不依赖于先前请求的结果,那么您可以同时执行 2-3 个相同的 API 请求可以同时做不同的请求,很多是并行的。只有当其中一些请求失败时,才重试第二次。这种技术不仅可以让您提高总体性能,还可以减少 API 服务器上不必要的重量。
-
这是一个移动客户端的搜索功能,所以是的,这些功能甚至可以在当前高峰使用时同时运行 20-30 次。你推荐在这种情况下使用 threading 模块吗?
-
顺便说一句,有一些自动化工具可以自动转换 Py2->Py3。一个是Modernizer,另一个是Futurize。第二个是一件很酷的事情,因为它以这样一种方式进行转换,之后 Py2 和 Py3 都可以运行相同的脚本。此外,Futurizer 只是在脚本的开头添加了额外的导入,这些导入使您的进一步代码可以同时由 Py2 和 Py3 运行,因此您的脚本几乎没有修改但升级了。我心目中的理想解决方案。
-
顺便说一句,@ti7 刚刚更新了他对另一个守护进程解决方案的回答,而不是
daemon = True构造函数参数,您可以在 Python 2 中的线程t实例上使用t.daemon = True。
标签: python python-2.7 multiprocessing