Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/python-2.7/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何同时启动两个功能,而只等待更快的一个?_Python_Python 2.7_Multiprocessing - Fatal编程技术网

Python 如何同时启动两个功能,而只等待更快的一个?

Python 如何同时启动两个功能,而只等待更快的一个?,python,python-2.7,multiprocessing,Python,Python 2.7,Multiprocessing,我有一个工作代码,但不确定这是正确的方法。我有两个函数,它们都发出一个API请求,可能需要1到5秒之间的任意时间,但它们都被设计为返回相同的输出。我想同时运行这两个程序,一旦更快的程序完成了它的工作,就终止另一个程序并放弃它将返回的任何程序 p1 = Process(target = search1, args=(name) ) p2 = Process(target = search2, args=(name) ) if __name__=='__main__': p1.start(

我有一个工作代码,但不确定这是正确的方法。我有两个函数,它们都发出一个API请求,可能需要1到5秒之间的任意时间,但它们都被设计为返回相同的输出。我想同时运行这两个程序,一旦更快的程序完成了它的工作,就终止另一个程序并放弃它将返回的任何程序

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())
如果您多次发出相同的请求,最好只执行一次,然后联系服务所有者以提高其性能。(例如,它可能正在分发连接,其中一个节点非常慢)

正如@Arty所指出的,使用将比创建过程更轻松,因此更高效。您可以将线程设置为守护进程,这样它们就不需要通过
.join()
ed退出(在所有线程完成之前阻止程序退出)

异步逻辑可能会更快一些,但这可能会让人感到沮丧,尤其是在Python2中。此外,您可能会发现,如果您使用的是第三方库,例如,加载所需库的速度非常慢,并且会降低总体性能

有了线程,您可能会发现获取结果并将其放入一个线程安全且可扩展的应用程序中非常方便

粗线示例

从uuu未来uuu导入打印功能#打印(x)到打印x
导入队列
导入线程
#如果这些逻辑相同,请使用参数进行区分
#否则,您可以拥有任意数量的独特功能,
#每个人都提出了不同的要求
def发出请求(请求结果、请求参数):
result=“发出请求所需的任何逻辑”
Q_result.put(result)#将结果放入队列
列出不同的请求参数=[]。#填写所需内容
Q_result=queue.queue()#创建一个队列以保存结果
#迭代输入参数(可以是目标函数列表)
对于不同请求参数列表中的请求参数:
t=线程。线程(
目标=提出请求,
args=(Q_结果,请求_args),
)
t、 daemon=True#在Python 3中通过arg设置
t、 开始()
#获取第一个结果,阻塞直到一个可用
打印(Q_result.get())
#程序退出并丢弃线程

您有很多这样的任务要做吗?因为对于数千个任务来说,启动和终止流程需要花费大量的时间和资源。另外,如果它只是一个API请求,那么您可能可以使用与您相同的方法,但对于来自
线程
模块的轻量级线程。但总的来说,你的方法很好,这是解决你任务的一种方法。但从某种意义上说,您的解决方案很好,因为当进程被终止时,所有资源都被释放。但是如果你使用线程,那么一些资源可能会泄漏。我还有一个想法——如果你必须执行许多任务、许多请求,并且你的下一个请求不依赖于前一个请求的结果,那么你可以同时执行2-3个相同的API请求,而不是同时执行不同的请求,许多请求是并行的。只有当其中一些请求失败时,才可以重试第二次。这项技术不仅可以提高总体性能,还可以减少API服务器上不必要的重量。这是移动客户端的一项搜索功能,因此可以在当前峰值使用率下同时运行20-30次。你建议在这种情况下使用线程模块吗?顺便说一句,有自动转换Py2->Py3的工具。一个是另一个是。第二个是一个很酷的东西,因为它转换的方式使得Py2和Py3都可以运行相同的脚本。此外,Futurizer只是在脚本的开头添加了额外的导入,导入使您的后续代码可以同时由Py2和Py3运行,因此您的脚本几乎没有修改,但已升级。顺便说一句,@ti7刚刚将他的答案更新为守护进程的另一个解决方案,而不是
daemon=True
构造函数参数,您可以在Python 2中的线程
t
实例上使用
t.daemon=True
。您好!我根据你的建议编辑了我的代码,现在看看这个问题。问题是它不接受daemon作为init中的关键字。如果我删除它,它会运行,但较慢的线程会阻止退出。可能是什么问题?@AkosF抱歉!我已经有一分钟没有使用Python2了;这是一个应该在启动线程之前设置的属性-我已经更新了我的示例!医生:非常感谢你的帮助,现在它很有魅力!嗨@ti7!希望您看到这个问题:)如果两个线程都出现异常而失败,那么主线程将永远被阻塞,那么我正在努力处理这种情况。知道在这种情况下如何安全地退出两个线程吗?提前多谢@AkosF请提出一个新问题并将其链接到此处,再次标记我,但
Queue.get()
接受一个超时参数,这将允许您停止阻止并继续退出(或任何您喜欢的默认值)文档: