如何同时启动两个功能,只等待更快的一个?
How to start two functions at the same time and only wait for the faster one?
我有一个工作代码,但不确定这是正确的方法。我有两个函数,都发出一个 API 请求,可以花费 1 到 5 秒之间的任意时间,但两者都设计为 return 相同的输出。我想同时 运行 这两个,一旦更快完成它的工作,终止另一个并放弃它会 return.
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 秒),有时两者都 returning 如果两者花费的时间差不多。我测试了很多次并且有效,但这是正确的方法吗?这种方法有什么问题吗?
--- 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())
如果您多次发出相同的请求,最好只执行一次并联系服务所有者以提高其性能。 (例如,它可能正在分发连接并且其中一个节点非常慢)。
正如 @Arty 指出的那样,使用 threads 创建起来比流程更轻松,因此性能更高。您可以使线程成为守护进程,因此它们不需要 .join()
ed 退出(阻塞程序退出,直到所有线程都完成)。
异步逻辑可能仍然快一点,但推理起来可能会令人沮丧,尤其是在 Python 2. 此外,如果您使用的是第三方库,例如 Twisted's Defferred, 加载所需的库非常慢并降低整体性能。
使用线程,您可能会发现获取结果并将其放入 queue.Queue
, which is both threadsafe and can block until content is available 中很方便。
粗线程示例
from __future__ import print_function # print(x) over print x
import queue
import threading
# if these are the same logic, use an argument to differentiate
# otherwise you could have any number of unique functions,
# each of which makes some different request
def make_request(Q_result, request_args):
result = "whatever logic is needed to make request A"
Q_result.put(result) # put the result into the Queue
list_of_different_request_args = [] # fill with whatever you need
Q_result = queue.Queue() # create a Queue to hold the result(s)
# iterate over input args (could be list of target functions instead)
for request_args in list_of_different_request_args:
t = threading.Thread(
target=make_request,
args=(Q_result, request_args),
)
t.daemon = True # set via arg in Python 3
t.start()
# get the first result, blocking until one is available
print(Q_result.get())
# program exits and discards threads
我有一个工作代码,但不确定这是正确的方法。我有两个函数,都发出一个 API 请求,可以花费 1 到 5 秒之间的任意时间,但两者都设计为 return 相同的输出。我想同时 运行 这两个,一旦更快完成它的工作,终止另一个并放弃它会 return.
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 秒),有时两者都 returning 如果两者花费的时间差不多。我测试了很多次并且有效,但这是正确的方法吗?这种方法有什么问题吗?
--- 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())
如果您多次发出相同的请求,最好只执行一次并联系服务所有者以提高其性能。 (例如,它可能正在分发连接并且其中一个节点非常慢)。
正如 @Arty 指出的那样,使用 threads 创建起来比流程更轻松,因此性能更高。您可以使线程成为守护进程,因此它们不需要 .join()
ed 退出(阻塞程序退出,直到所有线程都完成)。
异步逻辑可能仍然快一点,但推理起来可能会令人沮丧,尤其是在 Python 2. 此外,如果您使用的是第三方库,例如 Twisted's Defferred, 加载所需的库非常慢并降低整体性能。
使用线程,您可能会发现获取结果并将其放入 queue.Queue
, which is both threadsafe and can block until content is available 中很方便。
粗线程示例
from __future__ import print_function # print(x) over print x
import queue
import threading
# if these are the same logic, use an argument to differentiate
# otherwise you could have any number of unique functions,
# each of which makes some different request
def make_request(Q_result, request_args):
result = "whatever logic is needed to make request A"
Q_result.put(result) # put the result into the Queue
list_of_different_request_args = [] # fill with whatever you need
Q_result = queue.Queue() # create a Queue to hold the result(s)
# iterate over input args (could be list of target functions instead)
for request_args in list_of_different_request_args:
t = threading.Thread(
target=make_request,
args=(Q_result, request_args),
)
t.daemon = True # set via arg in Python 3
t.start()
# get the first result, blocking until one is available
print(Q_result.get())
# program exits and discards threads