Python 如何在concurrent.futures.ThreadPoolExecutor中使用锁而不导致死锁?
我正在处理Jira changelog历史数据,由于数据量很大,而且大多数处理时间都是基于I/O的,因此我认为异步方法可能会很好地工作 我有一个所有Python 如何在concurrent.futures.ThreadPoolExecutor中使用锁而不导致死锁?,python,multithreading,concurrent.futures,Python,Multithreading,Concurrent.futures,我正在处理Jira changelog历史数据,由于数据量很大,而且大多数处理时间都是基于I/O的,因此我认为异步方法可能会很好地工作 我有一个所有issue\u id的列表,我将其输入一个函数,该函数通过jira pythonapi发出请求,将信息提取到dict,然后通过传入的DictWriter将其写出。为了保证线程安全,我从threading模块导入了一个Lock()。在测试中,它似乎在某一点陷入僵局,只是挂起。我在文档中注意到,如果任务相互依赖,那么它们可以挂起,我想这是由于我正在实现的
issue\u id
的列表,我将其输入一个函数,该函数通过jira python
api发出请求,将信息提取到dict
,然后通过传入的DictWriter
将其写出。为了保证线程安全,我从threading
模块导入了一个Lock()。在测试中,它似乎在某一点陷入僵局,只是挂起。我在文档中注意到,如果任务相互依赖,那么它们可以挂起,我想这是由于我正在实现的锁造成的。我怎样才能防止这种情况发生
以下是我的代码供参考:
(此时代码中有一个名为keys
的列表,其中包含所有问题id)
编辑:我也很可能被Jira API限制了。您需要将exec
的结果存储到一个列表中,通常命名为futs
,然后循环调用该列表result()
,以获得结果,处理可能发生的任何错误
(我还想将exec
转换为executor
,因为这更为传统,而且可以避免覆盖内置的)
def write_issue_history(
jira_instance: JIRA,
issue_id: str,
writer: DictWriter,
lock: Lock):
logging.debug('Now processing data for issue {}'.format(issue_id))
changelog = jira_instance.issue(issue_id, expand='changelog').changelog
for history in changelog.histories:
created = history.created
for item in history.items:
to_write = dict(issue_id=issue_id)
to_write['date'] = created
to_write['field'] = item.field
to_write['changed_from'] = item.fromString
to_write['changed_to'] = item.toString
clean_data(to_write)
add_etl_fields(to_write)
print(to_write)
with lock:
print('Lock obtained')
writer.writerow(to_write)
if __name__ == '__main__':
with open('outfile.txt', 'w') as outf:
writer = DictWriter(
f=outf,
fieldnames=fieldnames,
delimiter='|',
extrasaction='ignore'
)
writer_lock = Lock()
with ThreadPoolExecutor(max_workers=5) as exec:
for key in keys[:5]:
exec.submit(
write_issue_history,
j,
key,
writer,
writer_lock
)
from traceback import print_exc
...
with ThreadPoolExecutor(max_workers=5) as executor:
futs = []
for key in keys[:5]:
futs.append( executor.submit(
write_issue_history,
j,
key,
writer,
writer_lock)
)
for fut in futs:
try:
fut.result()
except Exception as e:
print_exc()