这里是详细问题:
我想使用多线程方法来执行批处理http请求,然后将所有这些结果收集到列表中并对所有项目进行排序。
因此,我想首先在主进程中定义一个空列表origin_list
,并在将origin_list
传递给正常线程之后,启动一些线程以将结果追加到该列表中。
然后我似乎在最后得到了预期的结果,所以我认为我最终得到了正确的结果列表,而没有线程锁定,因为该列表是可变对象,对吗?
我的主要代码如下:
def do_request_work(final_item_list,request_url):
request_results = request.get(request_url).text
# do request work
finnal_item_list.append(request_results )
def do_sort_work(final_item_list):
# do sort work
return final_item_list
def main():
f_item_list = []
request_list = [url1, url2, ...]
with ThreadPoolExecutor(max_workers=20) as executor:
executor.map(
partial(
do_request_work,
f_item_list
),
request_list)
sorted_list = do_sort_work(f_item_list)
任何评论都非常受欢迎。非常感谢。
答案 0 :(得分:1)
我认为,即使不考虑线程安全性,这也是一个非常可疑的解决方案。
首先python
有GIL,
在CPython中,全局解释器锁或GIL是一个互斥锁, 保护对Python对象的访问,防止多个线程 一次执行Python字节码。
因此,我对这里的性能优势感到怀疑,甚至注意到了
可能阻塞或长时间运行的操作,例如I / O,映像 处理,以及NumPy号码处理都发生在GIL之外。
所有python
工作将一次执行一个线程。
从另一个角度看,相同的锁可以帮助您确保线程安全,因此一次只有一个线程会修改final_item_list
,但我不确定。
无论如何,我在这里使用multiprocessing
module和集成的并行map
:
from multiprocessing import Pool
def do_request_work(request_url):
request_results = request.get(request_url).text
# do request work
return request_results
if __name__ == '__main__':
request_list = [url1, url2, ...]
with Pool(20) as p:
f_item_list = p.map(do_request_work, request_list)
这将保证您并行执行请求的无锁执行,因为每个进程将仅接收其工作的一部分,并在准备就绪时仅返回结果。
答案 1 :(得分:0)
查看此线程:I'm seeking advise on multi-tasking on Python36 platform, Procedure setup。
与python3.5 +
有关Running Tasks Concurrently¶
awaitable asyncio.gather(*aws, loop=None, return_exceptions=False)
Run awaitable objects in the aws sequence concurrently.
我经常使用它,只是要知道它不是线程安全的,所以不要在内部更改值,否则您将使用deepcopy。
要注意的其他事项: