python - 如何防止并发期货库循环先前迭代的项目?
问题描述
我有一个lst1
数字 ID(大约 300K ID)的列表(),我将其传递给 API,并将 api 结果附加到另一个列表(lst
)中,如下所示:
lst = []
lst1 = [1,2,3,4,5,6]
print(len(lst1))
counter = 0
for i in lst1:
url = 'url.com/Id={}'.format(i)
while True:
try:
xml_data1 = requests.get(url).text
counter = counter+ 1
print(counter)
#print(xml_data1)
break
except requests.exceptions.RequestException as e:
print(e)
lst.append(xml_data1)
当我应用 future.concurrent 库时,代码会不断循环相同的 ID。我可以告诉这一点,因为柜台号码不断重复,我该如何防止这种情况?
我如何应用 futures.concurrent 库的代码:
def get_data(xml):
print(len(lst1))
#counter = 0
for i in lst1:
url = 'url.com/Id={}'.format(i)
while True:
try:
xml_data1 = requests.get(url).text
counter = counter+ 1
print(counter)
#print(xml_data1)
break
except requests.exceptions.RequestException as e:
print(e)
lst.append(xml_data1)
with futures.ThreadPoolExecutor() as executor:
df_list = executor.map(get_data, lst1)
编辑:
def get_data(xml):
#counter = 0
for i in lst1:
url = 'url.com/Id={}'.format(i)
while True:
try:
xml_data1 = requests.get(url).text
counter = next(counter_object)
print(counter)
#print(xml_data1)
break
except requests.exceptions.RequestException as e:
print(e)
lst.append(xml_data1)
return lst
with futures.ThreadPoolExecutor() as executor:
lst = executor.map(get_data, lst1)
解决方案
整数是不可变的。所以你可以让你的计数器全局使用
global counter
您还可以使用定义一个全局counter
对象(不是整数)itertools.count
这是我的首选方法,因为它避免了global
在像整数这样的不可变对象上使用,这总是会导致错误和误解。
import itertools
counter_object = itertools.count() # default: starts at 0
现在:
counter = counter+ 1
变成:
counter = next(counter_object)
并且工作线程之间的值不会相同。
这依赖于 CPython 具有使操作安全的全局解释器锁这一事实。如果您不使用 CPython,则必须使用线程锁定机制来保护对象免受并发修改。
另一个问题是不get_data
应该返回一个列表而是一个项目。让我们executor.map
创建列表(并且您的循环是无用/有害的,因为它会乘以计算次数)
所以总结一下:
def get_data(xml):
url = 'url.com/Id={}'.format(xml)
while True:
try:
xml_data1 = requests.get(url).text
counter = next(counter_object)
print(counter)
break
except requests.exceptions.RequestException as e:
print(e)
return xml_data1
最后,executor.map
被迭代。要创建一个列表,您必须对其强制迭代:
with futures.ThreadPoolExecutor() as executor:
df_list = list(executor.map(get_data, lst1))
推荐阅读
- jquery - 如何将 flatpickr 替换为 angular material design datepicker
- azure - Azure IoT Edge 批处理行为
- ios - 创建新故事板时如何快速优化内存?
- php - 使用 2 while 循环并在 PHP 中移动下一步
- c# - 是否可以将某些内容从对话框窗口拖到 C# 中的父级
- cefsharp - 执行 RDP 时 VueJS 应用程序和 CEF Sharp 之间的通信丢失
- c++ - 为什么 long l = 0x80000000 是一个正数?
- java - Intellij 构建 scala 模块显示错误与 scalac:Error:scala/xml/MetaData
- javascript - (WEBPACK) 将 publicpPath 添加到脚本并链接到生成的 HTML
- javascript - 通过升序和降序切换 lodash order