Python的并发处理能力臭名昭著。先撇开线程以及GIL方面的问题不说,我觉得多线程问题的根源不在技术上而在于理念。大部分关于Pyhon线程和多进程的资料虽然都很不错,但却过于细节。这些资料讲的都是虎头蛇尾,到了真正实际使用的部分却草草结束了。 传统例子在DDG https://duckduckgo.com/搜索“Python threading 标准线程多进程,生产者/消费者示例: 这里是代码截图,如果用其他模式贴出大段代码会很不美观。文本模式点这里 here Mmm.. 感觉像是java代码 在此我不想印证采用生产者/消费者模式来处理线程/多进程是错误的— 确实没问题。实际上这也是解决很多问题的最佳选择。但是,我却不认为这是日常工作中常用的方式。 问题所在一开始,你需要一个执行下面操作的铺垫类。接着,你需要创建一个传递对象的队列,并在队列两端实时监听以完成任务。(很有可能需要两个队列互相通信或者存储数据) Worker越多,问题越大. 下一步,你可能会考虑把这些worker放入一个线程池一边提高Python的处理速度。下面是 Seriously, Medium. Fix your code support. Code is Here. 感觉效果应该很好,但是看看这些代码!初始化方法、线程跟踪,最糟的是,如果你也和我一样是个容易犯死锁问题的人,这里的join语句就要出错了。这样就开始变得更加复杂了! 到现在为止都做了些什么?基本上没什么。上面的代码都是些基础功能,而且很容易出错。(天啊,我忘了写上在队列对象上调用task_done()方法(我懒得修复这个问题在重新截图)),这真是性价比太低。所幸的是,我们有更好的办法. 引入:Map Map是个很酷的小功能,也是简化Python并发代码的关键。对那些不太熟悉Map的来说,它有点类似Lisp.它就是序列化的功能映射功能. e.g. urls = [', ']results = map(urllib2.urlopen, urls) 这里调用urlopen方法,并把之前的调用结果全都返回并按顺序存储到一个集合中。这有点类似 results = []for url in urls: results.append(urllib2.urlopen(url)) Map能够处理集合按顺序遍历,最终将调用产生的结果保存在一个简单的集合当中。 为什么要提到它?因为在引入需要的包文件后,Map能大大简化并发的复杂度! 支持Map并发的包文件有两个: Multiprocessing,还有少为人知的但却功能强大的子文件 multiprocessing.dummy. . Digression这是啥东西?没听说过线程引用叫dummy的多进程包文件。我也是直到最近才知道。它在多进程的说明文档中也只被提到了一句。它的效果也只是让大家直到有这么个东西而已。这可真是营销的失误! Dummy是一个多进程包的完整拷贝。唯一不同的是,多进程包使用进程,而dummy使用线程(自然也有Python本身的一些限制)。所以一个有的另一个也有。这样在两种模式间切换就十分简单,并且在判断框架调用时使用的是IO还是CPU模式非常有帮助. |