我正在尝试使用 Yahoo Finance 的多个线程下载大量数据。我concurrent.futures.ThreadPoolExecutor
用来加快速度。一切都很顺利,直到我使用了所有可用的文件描述符(默认为 1024)。
当urllib.request.urlopen()
引发异常时,文件描述符保持打开状态(无论我使用的套接字超时)。通常,如果我仅从单个(主)线程运行内容,则会重用此文件描述符,因此不会发生此问题。但是,当这些异常urlopen()
调用从ThreadPoolExecutor
线程进行时,这些文件描述符保持打开状态。到目前为止,我想出的唯一解决方案是使用ProcessPoolExecutor
非常繁琐且效率低下的进程( )。必须有更聪明的方法来处理这个问题。
而且我想知道这是否是 Python 库中的一个错误,或者我只是做错了什么......
我在 Debian 上运行 Python 3.4.1(测试,内核 3.10-3-amd64)。
这是演示此行为的示例代码:
import concurrent
import concurrent.futures
import urllib.request
import os
import psutil
from time import sleep
def fetchfun(url):
urllib.request.urlopen(url)
def main():
print(os.getpid())
p = psutil.Process(os.getpid())
print(p.get_num_fds())
# this url doesn't exist
test_url = 'http://ichart.finance.yahoo.com/table.csv?s=YHOOxyz' + \
'&a=00&b=01&c=1900&d=11&e=31&f=2019&g=d'
with concurrent.futures.ThreadPoolExecutor(1) as executor:
futures = []
for i in range(100):
futures.append(executor.submit(fetchfun, test_url))
count = 0
for future in concurrent.futures.as_completed(futures):
count += 1
print("{}: {} (ex: {})".format(count, p.get_num_fds(), future.exception()))
print(os.getpid())
sleep(60)
if __name__ == "__main__":
main()