Python3废弃了原来的thread模块,换成了高级的threading模块,concurrent.futures是使用线程的最新方式。(Python3把thread模块重命名为_thread,以此强调这是低层实现, 不应该在应用代码中使用)如果使用场景较复杂,需要更高级的工具multiprocessing模块和threading模块。
concurrent.futures模块提供了一个用于异步执行调用的高级接口
from concurrent import futures
from time import sleep
def printer(n):
sleep(n)
print("sleep {}s output {}".format(n, n))
return n*n
executor = futures.ThreadPoolExecutor(max_workers=3)
results = executor.map(printer, [4,3,2,1,0])
for i, result in enumerate(results):
print('done ! result {}: {}'.format(i, result))
.result_iterator at 0x7f86398a6620>
sleep 2s output 2
sleep 3s output 3
sleep 0s output 0
sleep 1s output 1
sleep 4s output 4
done! result 16
done! result 9
done! result 4
done! result 1
done! result 0
ThreadPoolExecutor构造方法的max_workers参数是指定线程数,任务开始会执行 printer(4) printer(3) printer(2)
import concurrent.futures
import urllib.request
URLS = ['http://www.baidu.com/',
'http://www.sina.com/',
'http://www.mi.com/',
'http://jd.com/',
'http://taobao.com/']
def load_url(url, timeout):
with urllib.request.urlopen(url, timeout=timeout) as conn:
return conn.read()
with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:
future_to_url = {executor.submit(load_url, url, 60): url for url in URLS}
print(future_to_url)
for future in concurrent.futures.as_completed(future_to_url):
url = future_to_url[future]
try:
data = future.result()
except Exception as exc:
print('%r generated an exception: %s' % (url, exc))
else:
print('%r page is %d bytes' % (url, len(data)))
{: 'http://www.baidu.com/',
: 'http://www.sina.com/',
: 'http://www.jd.com/',
: 'http://www.mi.com/',
: 'http://taobao.com/'}
'http://www.sina.com/' page is 601152 bytes
'http://www.baidu.com/' page is 111404 bytes
'http://www.mi.com/' page is 294910 bytes
'http://taobao.com/' page is 123740 bytes
'http://www.jd.com/' page is 123354 bytes
前三个Future的状态是 running, 因为有三个工作的线程。
import concurrent.futures
import math
PRIMES = [
112272535095293,
112582705942171,
112272535095293,
115280095190773,
115797848077099,
1099726899285419]
def is_prime(n):
if n % 2 == 0:
return False
sqrt_n = int(math.floor(math.sqrt(n)))
for i in range(3, sqrt_n + 1, 2):
if n % i == 0:
return False
return True
def main():
with concurrent.futures.ProcessPoolExecutor() as executor:
for number, prime in zip(PRIMES, executor.map(is_prime, PRIMES)):
print('%d is prime: %s' % (number, prime))
if __name__ == '__main__':
main()
ThreadPoolExecutor.__init__ 方法需要 max_workers 参数, 指定线程池中线程的数量。 在 ProcessPoolExecutor 类中, 那个参数是可选的, 而且大多数情况下不使用——默认值是os.cpu_count() 函数返回的 CPU 数量