如何在Python中使用线程?
我想了解Python中的线程。 我已经看过文档和示例,但坦率地说,很多示例都非常复杂,我无法理解它们。
你如何清楚地显示被划分为多线程的任务?
自从2010年提出这个问题以来,已经真正简化了如何用map和pool进行python简单的多线程处理。
下面的代码来自一篇文章/博客文章,你一定要检查(无从属关系) - 并行性在一行中:日常线程任务的更好模型 。 我将在下面总结 - 它最终只是几行代码:
from multiprocessing.dummy import Pool as ThreadPool
pool = ThreadPool(4)
results = pool.map(my_function, my_array)
以下是多线程版本:
results = []
for item in my_array:
results.append(my_function(item))
描述
Map是一个很酷的小函数,也是将并行机制轻松注入Python代码的关键。 对于那些不熟悉的人来说,地图可以从Lisp等功能语言中解脱出来。 它是一个将另一个函数映射到一个序列上的函数。
Map处理对我们的迭代,应用函数,并将所有结果存储在最后的便捷列表中。
履行
并行版本的map函数由两个库提供:多处理,以及其已知但同样非常棒的步骤子:multiprocessing.dummy。
multiprocessing.dummy
与多处理模块完全相同,但使用线程代替(一个重要的区别 - 对CPU密集型任务使用多个进程;对于(和在)IO中使用线程):
multiprocessing.dummy复制多处理的API,但不过是线程模块的一个包装。
import urllib2
from multiprocessing.dummy import Pool as ThreadPool
urls = [
'http://www.python.org',
'http://www.python.org/about/',
'http://www.onlamp.com/pub/a/python/2003/04/17/metaclasses.html',
'http://www.python.org/doc/',
'http://www.python.org/download/',
'http://www.python.org/getit/',
'http://www.python.org/community/',
'https://wiki.python.org/moin/',
]
# make the Pool of workers
pool = ThreadPool(4)
# open the urls in their own threads
# and return the results
results = pool.map(urllib2.urlopen, urls)
# close the pool and wait for the work to finish
pool.close()
pool.join()
时间结果:
Single thread: 14.4 seconds
4 Pool: 3.1 seconds
8 Pool: 1.4 seconds
13 Pool: 1.3 seconds
传递多个参数 (只适用于Python 3.3及更高版本):
要传递多个数组:
results = pool.starmap(function, zip(list_a, list_b))
或者传递一个常量和一个数组:
results = pool.starmap(function, zip(itertools.repeat(constant), list_a))
如果您使用的是早期版本的Python,则可以通过此解决方法传递多个参数。
(感谢user136036提供有用的评论)
这里有一个简单的例子:你需要尝试一些替代URL并返回第一个URL的内容来回应。
import Queue
import threading
import urllib2
# called by each thread
def get_url(q, url):
q.put(urllib2.urlopen(url).read())
theurls = ["http://google.com", "http://yahoo.com"]
q = Queue.Queue()
for u in theurls:
t = threading.Thread(target=get_url, args = (q,u))
t.daemon = True
t.start()
s = q.get()
print s
这是线程用作简单优化的一种情况:每个子线程正在等待URL解析和响应,以便将其内容放入队列; 每个线程都是一个守护进程(如果主线程结束,将不会保留进程 - 这比通常更常见); 主线程启动所有的子线程,做一个get
队列等待,直到其中一人已经做了put
,然后发出的结果,并终止(这需要下可能仍在运行的所有子线程,因为他们是守护线程)。
在Python中正确使用线程总是与I / O操作相连接(因为CPython无论如何都不使用多个核心来运行CPU绑定任务,线程的唯一原因并不是阻塞进程,而是等待某些I / O )。 顺便提一下,队列几乎总是将工作排除在外并且/或者收集工作结果的最佳方式,而且它们本质上是线程安全的,因此它们可以让您免于担心锁,条件,事件,信号量以及其他互操作性问题,线程协调/通信概念。
注意:对于Python中的实际并行化,您应该使用多处理模块来并行执行多个进程(由于全局解释器锁定,Python线程提供了交错,但实际上是串行执行的,而不是并行执行的,交错I / O操作)。
然而,如果你只是在寻找交错(或者正在做I / O操作,尽管全局解释器锁定可以并行化),那么线程模块就是开始的地方。 作为一个非常简单的例子,让我们考虑通过并行求和子范围来求和大范围的问题:
import threading
class SummingThread(threading.Thread):
def __init__(self,low,high):
super(SummingThread, self).__init__()
self.low=low
self.high=high
self.total=0
def run(self):
for i in range(self.low,self.high):
self.total+=i
thread1 = SummingThread(0,500000)
thread2 = SummingThread(500000,1000000)
thread1.start() # This actually causes the thread to run
thread2.start()
thread1.join() # This waits until the thread has completed
thread2.join()
# At this point, both threads have completed
result = thread1.total + thread2.total
print result
请注意,以上是一个非常愚蠢的例子,因为它绝对没有I / O,并且由于全局解释器锁定而将在CPython中以串行方式执行,尽管它们是交错的(伴随着上下文切换的额外开销)。
链接地址: http://www.djcxy.com/p/40331.html上一篇: How to use threading in Python?
下一篇: Profiling C++ multi