如何防止并发期货库循环遍历以前迭代的项目?
How to prevent concurrent futures library from looping over previously iterated items?
我有一个数字 ID 列表 (lst1
)(大约 30 万个 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
您还可以使用 itertools.count
定义全局 counter
对象(非整数)
这是我的首选方法,因为它避免了在像整数这样的不可变对象上使用 global
,这总是会导致错误和误解。
import itertools
counter_object = itertools.count() # default: starts at 0
现在:
counter = counter+ 1
变为:
counter = next(counter_object)
并且工作线程之间的值不会相同。
这依赖于 CPython 具有使操作安全的全局解释器锁这一事实。如果您不使用 CPython,则必须使用线程锁定机制来保护对象免受并发修改。
另一个问题是 get_data
不应该 return 一个列表,而是一个项目。让 executor.map
创建列表(你的循环是 useless/harmful 因为它乘以计算次数)
所以总结一下:
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
被迭代。要创建列表,您必须对其进行 force 迭代:
with futures.ThreadPoolExecutor() as executor:
df_list = list(executor.map(get_data, lst1))
我有一个数字 ID 列表 (lst1
)(大约 30 万个 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
您还可以使用 itertools.count
counter
对象(非整数)
这是我的首选方法,因为它避免了在像整数这样的不可变对象上使用 global
,这总是会导致错误和误解。
import itertools
counter_object = itertools.count() # default: starts at 0
现在:
counter = counter+ 1
变为:
counter = next(counter_object)
并且工作线程之间的值不会相同。
这依赖于 CPython 具有使操作安全的全局解释器锁这一事实。如果您不使用 CPython,则必须使用线程锁定机制来保护对象免受并发修改。
另一个问题是 get_data
不应该 return 一个列表,而是一个项目。让 executor.map
创建列表(你的循环是 useless/harmful 因为它乘以计算次数)
所以总结一下:
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
被迭代。要创建列表,您必须对其进行 force 迭代:
with futures.ThreadPoolExecutor() as executor:
df_list = list(executor.map(get_data, lst1))