python之路: 线程、进程和协程

进程和线程

既然看到这一章,那么你肯定知道现在的系统都是支持“多任务”的操作,比如: Mac OS X,UNIX,Linux,Windows等。

多任务:简单地说就是同时运行多个任务。譬如:你可以一边看小电影,一边用word写感受,在一边录制,这就是多任务,至少同时有3个任务正在运行。还有很多任务在后台运行,只是桌面上没有显示而已。

 现在,多核CPU已经很普遍了,但是,即使在过去单核的时代,也是可以执行多任务的。由于CPU执行代码都是顺序执行的,那么单核CPU是怎么执行多任务的呢?答案就是:操作系统轮流让各个任务交替执行,任务1执行0.01秒,任务2执行0.01秒,在切换到任务3上......这样反复下去。表面看都是交替执行的,但是,CPU的执行速度太快,所以我们感觉就像所有任务都在同时执行一样。

真正的同时执行多任务只能在多核CPU上实现,但是,任务数量远远多于CPU的核心数量,所以操作系统也会自动把很多任务轮流调度到每个核心上执行。

对于操作系统来说,一个任务就是一个进程(Process)有些进程还不止同时干一件事,比如word,它可以同时进行打字、拼写检查,打印等事情 。在一个进程内部,要同时干多件事,所以,一个进程至少有一个线程。当然,像word这种复杂的进程可以有多个线程,多个线程可以同时执行,多线程的执行方式和多进程是一样的,也是由操作系统在多个线程之前快速的切换,让每一个线程都在短暂地交替运行,看起来就像同时执行一样。当然,真正地同时支持多线程需要多核CPU才可能实现。

前面写的所有Python程序,都是执行单任务的进程,也就是只有一个线程。如果要同时执行多个任务,请继续往下看。

有两种解决方案:

一种是启动多个进程,每个进程虽然只有一个线程,但多个进程可以一块执行多个任务。

还有一种方法是启动一个进程,在一个进程内启动多个线程,这样,多个线程也可以一块执行多个任务。

第三个方法就是启动多个进程,每个进程在启动多个线程,这样同时执行的任务就更多了,当然这中模型更复杂,实际很少采用。

总结以下就是,多任务的实现有3种方式:

  • 多进程模式
  • 多线程模式
  • 多进程+多线程模式

 同时支持多个任务通常各个任务之间并不是没有关联的,二是需要相互通信和协调,有时,任务1必须暂停等待任务2完成才能继续执行,有时,任务3和任务4又不能同时执行,所以,多进程和多线程的程序的复杂度要远远高于我们前面写的单进程单线程的程序。

因为复杂度高,调试困难,所以,不是迫不得已,我们也不想编写多任务。但是,有很多时候,没有多任务还真不行。Python既支持多进程,又支持多线程,我们会讨论如何编写这两种多任务程序。

Python 多进程

 要让Python程序实现多进程,我们要先了解一些操作系统的相关知识。

Unix/Linux操作系统提供了一个fork()系统调用,它非常特殊。普通的函数调用,调用一次,返回一次,但是fork()调用一次,返回两次,因为操作系统自动把当前进程(称为父进程)复制了一份(称为子进程),然后,分别在父进程和子进程内返回。

子进程永远返回0,而父进程返回子进程的ID。这样做的理由是,一个父进程可以fork出很多子进程,所以,父进程要记下每一个子进程的ID,而子进程只需要调用getppid()就可以拿到父进程的ID。

Python的os模块封装了常见的系统调用,其中就包括fork,可以在Python程序中轻松创建子进程:

import os

print('Process (%s) start...' % os.getpid())
# Only works on Unix/Linux/Mac:
pid = os.fork()
if pid == 0:
    print('I am child process (%s) and my parent is %s.' % (os.getpid(), os.getppid()))
else:
    print('I (%s) just created a child process (%s).' % (os.getpid(), pid)) 

 运行结果如下:

Process (876) start...
I (876) just created a child process (877).
I am child process (877) and my parent is 876.

 由于Windows没有fork调用,上面的代码不能在Windows上运行。由于Mac系统是基于BSD(Unix的一种)内核,所以,在Mac下运行是没有问题的,推荐是用Mac下学习Python!

有了fork调用,一个进程在接到新任务时就可以复制出一个子进程来处理新任务,常见才Apache服务器就是由附近吃监听端口,每当有新的http请求时,就fork出子进程来处理新的http请求。

multiprocessing

from multiprocessing import Process, Queue
import os, time, random, threading
def fool(i):
    print 'say hi',i
if __name__ == '__main__':
    for i in range(1000):
        i = Queue()
        p = Process(target=fool,args=(i,))
        p.start()

执行结果:

say hi <multiprocessing.queues.Queue object at 0x00000000023552B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023552B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023452B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023152B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023152B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023352B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023352B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023552B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023652B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024252B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023552B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023652B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023952B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023252B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023252B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023252B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023152B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023452B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023552B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023252B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023452B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023452B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023352B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023152B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023352B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023852B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023152B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023652B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023552B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023952B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023852B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023352B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023452B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023752B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023852B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023152B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023252B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023352B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023252B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023752B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023952B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024552B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023652B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023452B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023952B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023552B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023252B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023252B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023152B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024152B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023752B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023552B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023552B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023552B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024352B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023352B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024452B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023752B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023352B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023852B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023352B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024452B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023452B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024152B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023852B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023852B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023352B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023652B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024152B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023452B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023452B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023652B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023552B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024352B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024352B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023252B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023152B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023452B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024452B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023552B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023252B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023352B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023652B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023552B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023152B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023352B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023352B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023352B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023152B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023452B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023252B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023552B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023552B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024152B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023452B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023852B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023552B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024652B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023852B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023652B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024252B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023652B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023952B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023452B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023152B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023852B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023352B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023552B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023152B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023252B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023252B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023752B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024252B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023752B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023752B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024152B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023552B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023552B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023252B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023852B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023752B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023352B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023152B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024452B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023652B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023352B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023152B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023852B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023952B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023652B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024352B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023852B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024252B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023452B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023652B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023652B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023152B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023852B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023352B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024352B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023552B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023152B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023352B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023652B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023652B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023452B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023252B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023852B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024152B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023952B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023852B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023852B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023752B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023852B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023652B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023352B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024152B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023552B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023252B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023452B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023652B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023652B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023252B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023352B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023952B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023352B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023952B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023852B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023852B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024352B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024252B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024252B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023452B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024352B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024452B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023552B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023552B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023452B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023452B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023152B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023852B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023652B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024252B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023852B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023552B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023352B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023552B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023852B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023552B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023152B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023152B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023552B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023652B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023852B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023652B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024352B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023552B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023252B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023652B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023852B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023152B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023652B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024152B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024152B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024852B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023752B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023652B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023352B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023952B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023652B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023252B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023952B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023852B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023652B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023752B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023452B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023652B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024652B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023252B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023352B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023352B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023852B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023352B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024652B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023452B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023852B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023252B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024152B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023652B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023352B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023252B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023952B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023152B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023652B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023852B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023952B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023852B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023652B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023452B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023852B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023252B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023652B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023652B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023352B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023552B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023952B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023252B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023752B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023552B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023752B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023352B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024552B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023652B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023652B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023752B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023652B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023752B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023152B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023752B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023852B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023652B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023452B0>
say hisay hi  <multiprocessing.queues.Queue object at 0x00000000022C52B0><multiprocessing.queues.Queue object at 0x00000000023D52B0>

say hi <multiprocessing.queues.Queue object at 0x00000000023052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023952B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023752B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023152B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023352B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023252B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023152B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023452B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023352B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023252B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023552B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023652B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023552B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023952B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023452B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023652B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023952B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023752B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023352B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023752B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023952B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023952B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023952B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023952B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023352B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023552B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024952B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023852B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024952B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023352B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023552B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023252B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023652B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023152B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023452B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024652B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023852B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023952B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023952B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023652B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023452B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023452B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023352B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023952B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023352B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023452B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023452B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023552B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023152B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023152B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023752B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023452B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023652B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023152B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023352B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023552B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023952B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023552B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023252B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023452B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023252B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023852B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024252B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023652B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023552B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023452B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023952B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023152B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024252B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024552B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023452B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023852B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024452B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023952B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023452B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023152B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023552B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023852B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023952B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023152B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023452B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023952B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023752B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023852B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023252B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023352B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023752B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023852B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023252B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023452B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023252B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023952B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023652B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024252B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023452B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024352B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023652B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023452B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023552B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023452B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023552B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023652B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023552B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023452B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023652B0>
say hisay hi <multiprocessing.queues.Queue object at 0x00000000022F52B0>
 <multiprocessing.queues.Queue object at 0x00000000024052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023752B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023652B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023952B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023952B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023852B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023752B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023452B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023552B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023752B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023552B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023252B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023952B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023852B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023252B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023352B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023952B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023552B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023252B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023252B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024852B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023652B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023052B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023452B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023352B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023652B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023152B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022D52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023652B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023552B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023652B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023C52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023352B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023852B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023252B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023152B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022F52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023852B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023552B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000024152B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023A52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023952B0>
say hi <multiprocessing.queues.Queue object at 0x00000000022B52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023E52B0>
say hi <multiprocessing.queues.Queue object at 0x00000000023652B0>
View Code

如果你打算编写多进程的服务程序,Unix/Linux无疑是正确的选择。由于Windows没有fork调用,而Python是跨平台的,自然应该提供一个跨平台的多进程支持。multiprocessing模块就是跨平台版本的多进程模块。

multiprocessing模块提供了一个process类来代表一个进程对象,下面的例子演示了启动一个子进程并等待其结束:

#!/usr/bin/env  python
#
 --*--coding:utf-8 --*--
from multiprocessing import Process
import os

# 子进程要执行的代码
def run_proc(name):
    print('Run child process %s (%s)...' % (name, os.getpid()))

if __name__=='__main__':
    print('Parent process %s.' % os.getpid())
    p = Process(target=run_proc, args=('test',))
    print('Child process will start.')
    p.start()
    p.join()
    print('Child process end.')

 执行结果如下:

Parent process 8608.
Child process will start.
Run child process test (8752)...
Child process end.

 创建子进程时,只需要传入一个执行函数和函数的参数,创建一个process实例,用start()方法启动,这样创建进程比fork()还要简单。

join()方法可以等待子进程结束后再继续往下运行,通常用于进程间的同步。

POOL

如果要启动大量的子进程,可以用进程池的方式批量创建子进程:

#!/usr/bin/env  python
#
 --*--coding:utf-8 --*--
from multiprocessing import Pool
import os, time, random

def long_time_task(name):
    print('Run task %s (%s)...' % (name, os.getpid()))
    start = time.time()
    time.sleep(random.random() * 3)
    end = time.time()
    print('Task %s runs %0.2f seconds.' % (name, (end - start)))

if __name__=='__main__':
    print('Parent process %s.' % os.getpid())
    p = Pool(4)
    for i in range(5):
        p.apply_async(long_time_task, args=(i,))
    print('Waiting for all subprocesses done...')
    p.close()
    p.join()
    print('All subprocesses done.')

 执行结果:

Parent process 9052.
Waiting for all subprocesses done...
Run task 0 (7832)...
Run task 1 (8388)...
Run task 2 (8224)...
Run task 3 (9272)...
Task 1 runs 1.00 seconds.
Run task 4 (8388)...
Task 2 runs 1.19 seconds.
Task 0 runs 1.85 seconds.
Task 3 runs 2.01 seconds.
Task 4 runs 1.65 seconds.
All subprocesses done.
执行结果

 代码解读:

对Pool对象调用join()方法会等待所有子进程执行完毕,调用join()之前必须先调用close(),调用close()之后就不能继续添加新的Process了。

请注意输出的结果,task 0,1,2,3是立即执行的,而task4是要等待前面某个task完成后才执行,这是因为pool的默认大小在我的电脑是上4,因此,最多同时执行4个进程。这是pool有意设计的限制,并不是操作系统的限制。如果改成:

p = Pool(5)

 就可以同时跑5个进程。

由于Pool的默认大小是CPU的核数,如果你的电脑拥有8核CPU,你要提交至少9个子进程才能看到上面的等待效果。

子进程

很多时候,子进程并不是自身,二是一个外部进程。我们创建了子进程后,还需要控制子进程的输入和输出。

subprocess模块可以让我们非常方便地启动一个子进程,然后控制其输入输出。

 下面的例子演示了如何在Python代码中运行命令nslookup www.python.org,这和命令知己运行的效果是一样的:

#!/usr/bin/env  python
#
 --*--coding:utf-8 --*--
import subprocess
print('$ nslookup www.python.org')
r = subprocess.call(['nslookup', 'www.python.org'])
print('Exit code:', r)

 运行结果:

$ nslookup www.python.org
Server:        192.168.19.4
Address:    192.168.19.4#53

Non-authoritative answer:
www.python.org    canonical name = python.map.fastly.net.
Name:    python.map.fastly.net
Address: 199.27.79.223

Exit code: 0

 如果子进程还需要输入,则可以通过communicate()方法输入:

import subprocess

print('$ nslookup')
p = subprocess.Popen(['nslookup'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
output, err = p.communicate(b'set q=mx\npython.org\nexit\n')
print(output.decode('utf-8'))
print('Exit code:', p.returncode)

 上面的代码相当于在命令执行nslookup,然后手动输入:

set q=mx
python.org
exit

 运行结果如下:

$ nslookup
Server:        192.168.19.4
Address:    192.168.19.4#53

Non-authoritative answer:
python.org    mail exchanger = 50 mail.python.org.

Authoritative answers can be found from:
mail.python.org    internet address = 82.94.164.166
mail.python.org    has AAAA address 2001:888:2000:d::a6


Exit code: 0

 进程间通信

Process之间肯定是需要通信的,操作系统提供了很多机制来实现进程间的通信。Python的multiprocessing模块包装了底层的机制,提供看Queue、Pipes等多种方式来交换数据。

我们以Queue为例,在父进程中创建两个子进程,一个往Queue里写数据,一个从Queue里读数据:

#!/usr/bin/env  python
#
 --*--coding:utf-8 --*--
from multiprocessing import Process, Queue
import os, time, random

# 写数据进程执行的代码:
def write(q):
    print('Process to write: %s' % os.getpid())
    for value in ['A''B''C']:
        print('Put %s to queue...' % value)
        q.put(value)
        time.sleep(random.random())

# 读数据进程执行的代码:
def read(q):
    print('Process to read: %s' % os.getpid())
    while True:
        value = q.get(True)
        print('Get %s from queue.' % value)

if __name__=='__main__':
    # 父进程创建Queue,并传给各个子进程:
    q = Queue()
    pw = Process(target=write, args=(q,))
    pr = Process(target=read, args=(q,))
    # 启动子进程pw,写入:
    pw.start()
    # 启动子进程pr,读取:
    pr.start()
    # 等待pw结束:
    pw.join()
    # pr进程里是死循环,无法等待其结束,只能强行终止:
    pr.terminate()

 运行结果:

Process to write: 9188
Put A to queue...
Process to read: 9540
Get A from queue.
Put B to queue...
Get B from queue.
Put C to queue...
Get C from queue.

 在Unix/Linux下,multiprocessing模块封装了fork()调用,使我们不需要关注fork()的细节。由于Windows没有fork调用,因此,multiprocessing需要“模拟”出fork的效果,父进程所有Python对象都必须通过pickle失败了。

进程数据共享

进程各自持有一份数据,默认无法共享数据

#!/usr/bin/env  python
# --*--coding:utf-8 --*--
from multiprocessing import Process
from multiprocessing import Manager

import time

li = []

def foo(i):
    li.append(i)
    print 'say hi',li
if __name__ == '__main__':
    for i in range(10):
        p = Process(target=foo,args=(i,))
        p.start()

    print 'ending',li

print 'ending',li
进程间默认无法数据共享

执行结果

ending []
say hi [1]
ending []
say hi [2]
ending []
say hi [0]
ending []
say hi [3]
ending []
say hi [6]
ending []
say hi [5]
ending []
say hi [4]
ending []
ending []
ending []
say hi [7]
ending []
say hi [8]
ending []
say hi [9]
执行结果

共享实例一

#!/usr/bin/env  python
# --*--coding:utf-8 --*--
from multiprocessing import Process,Array
temp = Array('i', [11,22,33,44])

def Foo(i):
    temp[i] = 100+i
    for item in temp:
        print i,'----->',item
if __name__ == '__main__':
    for i in range(4):
        p = Process(target=Foo,args=(i,))
        p.start()
Array

 执行结果:

1 -----> 11
1 -----> 101
1 -----> 33
1 -----> 44
0 -----> 100
0 -----> 22
0 -----> 33
0 -----> 44
2 -----> 11
2 -----> 22
2 -----> 102
2 -----> 44
3 -----> 11
3 -----> 22
3 -----> 33
3 -----> 103
Array结果

实例二:manage.dict()共享数据

from multiprocessing import Process,Manager
 
manage = Manager()
dic = manage.dict()
 
def Foo(i):
    dic[i] = 100+i
    print dic.values()
 
for i in range(2):
    p = Process(target=Foo,args=(i,))
    p.start()
    p.join()
manage.dict()

类型对应表

'c': ctypes.c_char,  'u': ctypes.c_wchar,
'b': ctypes.c_byte,  'B': ctypes.c_ubyte,
'h': ctypes.c_short, 'H': ctypes.c_ushort,
'i': ctypes.c_int,   'I': ctypes.c_uint,
'l': ctypes.c_long,  'L': ctypes.c_ulong,
'f': ctypes.c_float, 'd': ctypes.c_double
View Code

 当创建进程时(非使用时),共享数据会被拿到子进程中,当进程中执行完毕后,在赋值给原值。

#!/usr/bin/env  python
# --*--coding:utf-8 --*--
from multiprocessing import Process, Array, RLock

def Foo(lock,temp,i):
    """
    将第0个数加100
    """
    lock.acquire()
    temp[0] = 100+i
    for item in temp:
        print i,'----->',item
    lock.release()

lock = RLock()
temp = Array('i', [11223344])

for i in range(20):
    p = Process(target=Foo,args=(lock,temp,i,))
    p.start()
进程锁实例

 进程池

进程池内部维护一个进程序列,当使用时,则去进程池中获取一个进程,如果进程池序列中没有可供使用的进程,那么程序就会等待,知道进程池中有可用进程为止。

进程池中有两个方法:

 

  • apply
  • apply_async 

 

#!/usr/bin/env  python
# --*--coding:utf-8 --*--
from  multiprocessing import Process,Pool
import time

def Foo(i):
    time.sleep(2)
    return i+100

def Bar(arg):
    print arg

pool = Pool(5)
# print pool.apply(Foo,(1,))
#print pool.apply_async(func =Foo, args=(1,)).get()
for i in range(10):
    pool.apply_async(func=Foo, args=(i,),callback=Bar)

print 'end'
pool.close()
pool.join()#进程池中进程执行完毕后再关闭,如果注释,那么程序直接关闭。

Python 多线程 

 多任务可以由多进程完成,也可以由一个进程内的多线程完成。

 我们前面提到了进程是由若干进程组成的,一个进程至少有一个线程。

由于线程是操作系统直接支持的执行单元,因此,高级语言通常都内置多线程的支持,Python也不例外,并且,Python的线程是真正的Posix Thread,而不是模拟出来的线程。

Python的标准库提供了两个模块:_thread和threading,_thread是低级模块,threading是高级模块,对_thread进行了封装。绝大多数情况下,我们只需要使用threading这个高级模块。

启动一个线程就是把一个函数传入并创建Thread实例,然后调用start()开始执行:

#!/usr/bin/env  python
#
 --*--coding:utf-8 --*--
import time, threading

# 新线程执行的代码:
def loop():
    print('thread %s is running...' % threading.current_thread().name)
    n = 0
    while n < 5:
        n = n + 1
        print('thread %s >>> %s' % (threading.current_thread().name, n))
        time.sleep(1)
    print('thread %s ended.' % threading.current_thread().name)

print('thread %s is running...' % threading.current_thread().name)
t = threading.Thread(target=loop, name='LoopThread')
t.start()
t.join()
print('thread %s ended.' % threading.current_thread().name)
实例一

来一个反的

#!/usr/bin/env python
#
 -*- coding:utf-8 -*-
 
import threading
import time

def show(arg):
    time.sleep(1)
    print 'thread'+str(arg)

for i in range(10):
    t = threading.Thread(target=show, args=(i,))
    t.start()

print 'main thread stop'
实例二

执行结果:

thread MainThread is running...
thread LoopThread is running...
thread LoopThread >>> 1
thread LoopThread >>> 2
thread LoopThread >>> 3
thread LoopThread >>> 4
thread LoopThread >>> 5
thread LoopThread ended.
thread MainThread ended.
实例一
main thread stop
thread3thread0thread4thread1thread5thread2





thread7thread9

 thread8thread6
实例二

实例一: 

 由于任何进程默认就会启动一个线程,我们把该线程称为主线程,主线程又可以启动新的线程,Python的threading模块有个current_thread()函数,它永远返回当前线程的实例。主线程实例的名字叫MainThread,子线程的名字在创建时指定,我们用LoopThread命名子线程。名字仅仅在打印时用来显示,完全没有其它意义,如果不起名字Python就自动给线程命名为Thread-1,Thread-2........

实例二:

上述代码创建了10个“前台”线程,然后控制器就交给了CPU,CPU根据指定算法进行调度,分片执行指令。

更多方法:

  • start 线程准备就绪,等待CPU调度
  • setName 为线程设置名称
  • getName 获取线程名称
  • setDaemon   设置为后台线程或前台线程(默认)
如果是后台线程,主线程执行过程中,后台线程也在进行,主线程执行完毕后,后台线程不论成功与否,均停止

如果是前台线程,主线程执行过程中,前台线程也在进行,主线程执行完毕后,等待前台线程也执行完毕后,程序停止。

  • join  逐个执行每个线程,执行完毕后继续往下执行,该方法使得多线程变得无意义
  • run 线程被CPU调度后执行Thread类对象的run方法

线程锁(Lock

多线程和多进程最大的不同之处在于,多进程中,同一个变量,各自有一份拷贝存在于每个进程中,相互之间不受影响,而多线程中,所有变量都由所有线程共享,所以,任何一个变量都可以被任何一个线程修改,因此,线程之间共享数据最大的危险在于多个线程同时改一个变量,把内容给改乱了。

来看看多个线程同时操作一个变量怎么把内容给改乱了:

#!/usr/bin/env python
#
 -*- coding:utf-8 -*-
import time, threading

# 假定这是你的银行存款:
balance = 0

def change_it(n):
    # 先存后取,结果应该为0:
    global balance
    balance = balance + n
    balance = balance - n

def run_thread(n):
    for i in range(100000):
        change_it(n)

t1 = threading.Thread(target=run_thread, args=(5,))
t2 = threading.Thread(target=run_thread, args=(8,))
t1.start()
t2.start()
t1.join()
t2.join()
print(balance)
实例一
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import threading
import time

gl_num = 0

def show(arg):
    global gl_num
    time.sleep(1)
    gl_num +=1
    print gl_num

for i in range(10):
    t = threading.Thread(target=show, args=(i,))
    t.start()

print 'main thread stop'
实例二

实例一 我们定义了一个共享变量balance,初始值为0,并且启动两个线程,先存后取,理论上结果应该为0,但是,由于线程的调度是由操作系统决定是,当t1、t2交替执行时,只要循环次数足够多,balance的结果就不一定是0了。

原因是因为高级语言的一条语句在CPU执行时是若干条语句,即使一个简单的计算:

balance = balance + n

 也分两步:

 1、计算balance + n ,存入临时变量中;

 2、将临时变量的值赋给balance。

也就是可以看成:

x = balance + n
balance = x

 由于x是局部变量,两个线程各自都有自己的X,当代码正常执行时:

初始值 balance = 0

t1: x1 = balance + 5 # x1 = 0 + 5 = 5
t1: balance = x1     # balance = 5
t1: x1 = balance - 5 # x1 = 5 - 5 = 0
t1: balance = x1     # balance = 0

t2: x2 = balance + 8 # x2 = 0 + 8 = 8
t2: balance = x2     # balance = 8
t2: x2 = balance - 8 # x2 = 8 - 8 = 0
t2: balance = x2     # balance = 0

结果 balance = 0

 但是t1和t2是交替运行的,如果操作系统以下面的顺序执行t1、t2:

初始值 balance = 0

t1: x1 = balance + 5  # x1 = 0 + 5 = 5

t2: x2 = balance + 8  # x2 = 0 + 8 = 8
t2: balance = x2      # balance = 8

t1: balance = x1      # balance = 5
t1: x1 = balance - 5  # x1 = 5 - 5 = 0
t1: balance = x1      # balance = 0

t2: x2 = balance - 8  # x2 = 0 - 8 = -8
t2: balance = x2   # balance = -8

结果 balance = -8

 究其原因,是因为修改balance需要多条语句,而执行这几条语句时,线程可能中断,从而导致多个线程把同一个对象的内容改乱了。

两个线程同时一存一取,就可能导致余额不对,你肯定不希望你的银行存款莫名其妙地变成了负数,所以,我们必须确保一个线程在修改balance的时候,别的线程一定不能改。

如果我们要确保balance计算正确,就要给change_it()上一把锁,当某个线程开始执行change_it()时,我们说,该锁以后才能改。由于锁只有一个,无论多少线程,同一时刻最多只有一个线程持有该锁,所以,不会造成修改的冲突。创建一个锁就是通过threading.Lock()来实现:

balance = 0
lock = threading.Lock()

def run_thread(n):
    for i in range(100000):
        # 先要获取锁:
        lock.acquire()
        try:
            # 放心地改吧:
            change_it(n)
        finally:
            # 改完了一定要释放锁:
            lock.release()
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import threading
import time
   
gl_num = 0

lock = threading.RLock()

def Func():
    lock.acquire()#获取锁
    global gl_num
    gl_num +=1
    time.sleep(1)
    print gl_num
    lock.release()#释放锁

for i in range(10):
    t = threading.Thread(target=Func)
    t.start()
实例二

 当多个线程同时执行lock.acquire()时,只有一个线程能成功地获取锁,然后继续执行代码,其他线程就继续等待直到获得锁为止。

 获得锁的线程用完后一定要释放锁,否则那些等待的 线程将永远等待下去,成为死进程。所以我们用try...finally来确保锁一定会被释放。

锁的好处就是确保了某段关键代码只能由一个线程从头到尾完整地执行,坏处当然也有很多,首先是阻止了多线程并发执行,包含锁的某段代码实际上只能以单线程模式执行,笑脸就大大地下降了。其次,由于可以存在多个锁,不同的线程持有不同的锁,并试图获取对方的锁时,可能会造成死锁,导致多个线程全部挂起,即不能执行,也无法结束,只能靠操作系统强制终止。

事件

Python线程的事件用于主线程控制其他线程的执行,事件主要提供了三个方法set、wait、clear。

事件的处理机制:全局定义了一个“Flag”,如果“Flag”值为False,那么当程序执行even.wait方法时就会阻塞,如果“Flag”值为True,那么event.wait方法时便不再阻塞。 

  • clear:将“Flag”设置为False
  • set:将“Flag”设置为True
#!/usr/bin/env python
# -*- coding:utf-8 -*-
import threading


def do(event):
    print 'start'
    event.wait()
    print 'execute'


event_obj = threading.Event()
for i in range(10):
    t = threading.Thread(target=do, args=(event_obj,))
    t.start()

event_obj.clear()
inp = raw_input('input:')
if inp == 'true':
    event_obj.set()

多核CPU

如果你不幸拥有一个多核CPU,你肯定在想,多核应该可以同时执行多个线程。

如果写一个死循环的话,会出现什么情况呢?

打开Mac OS X的Activity Monitor,或者Windows的Task Manager,都可以监控某个进程的CPU使用率。

 我们可以监控到一个死循环线程会100%占用一个CPU。

如果有两个死循环线程,在多核CPU中,可以监控到会占用200%的CPU,也就是占用两个CPU核心。

要想把N核CPU的核心全部跑满,就必须启动N个死循环线程。

试试用Python写一个死循环:

import threading, multiprocessing

def loop():
    x = 0
    while True:
        x = x ^ 1

for i in range(multiprocessing.cpu_count()):
    t = threading.Thread(target=loop)
    t.start()

 启动与CPU核心数量相同的N个线程,在4核CPU上可以监控到CPU占用率仅有102%,也就是仅使用了一核。但是用C、C++或Java来改写相同的死循环,直接可以把全部核心跑满,4核就跑到400%,8核就跑到800%,为什么Python不行呢?

因为Python的线程虽然是真正的线程,但解释器执行代码时,有一个GIL锁:Global Interpreter Lock,任何Python线程执行前,必须先获得GIL锁,然后,每执行100条字节码,解释器就自动释放GIL锁,让别的线程有机会执行。这个GIL全局锁实际上把所有线程的执行代码都上了锁,所以,多线程在Python中只能交替执行,即使100个线程跑在100核CPU上,也只能用到1核。

GIL是Python解释器设计的历史遗留问题,通常我们用的解释器是官方实现的CPython,要真正利用多核,除非重写一个人不带GIL的解释器。

所以,在Python中,可以使用多线程,但不要指望能有效利用多核。如果一定要通过多线程利用多核,那只能通过C扩展来实现,不过这样就失去了Python简单易用的特点。

不过,也不用过于担心,Python虽然不能利用多线程实现多核任务,但可以通过多进程实现多核任务。多个Python进程有各自独立的GIL锁,互不影响。

协程

 线程和进程的操作是由程序触发系统接口,最后的执行者是系统;协程的操作则是程序员。

协程存在的意义:对于多线程应用,CPU通过切片的方式来切换线程间的执行,线程切换时需要耗时(保存状态,下次继续)。协程,则只使用一个线程,在一个线程中规定某个代码块执行顺序。

协程的使用场景:当程序中存在大量不需要CPU的操作时(IO),适用于协程;

greenlet

#!/usr/bin/env python
# -*- coding:utf-8 -*-
 
 
from greenlet import greenlet
 
 
def test1():
    print 12
    gr2.switch()
    print 34
    gr2.switch()
 
 
def test2():
    print 56
    gr1.switch()
    print 78
 
gr1 = greenlet(test1)
gr2 = greenlet(test2)
gr1.switch()
gevent
import gevent
 
def foo():
    print('Running in foo')
    gevent.sleep(0)
    print('Explicit context switch to foo again')
 
def bar():
    print('Explicit context to bar')
    gevent.sleep(0)
    print('Implicit context switch back to bar')
 
gevent.joinall([
    gevent.spawn(foo),
    gevent.spawn(bar),
])

 遇到IO操作自动切换:

from gevent import monkey; monkey.patch_all()
import gevent
import urllib2

def f(url):
    print('GET: %s' % url)
    resp = urllib2.urlopen(url)
    data = resp.read()
    print('%d bytes received from %s.' % (len(data), url))

gevent.joinall([
        gevent.spawn(f, 'https://www.python.org/'),
        gevent.spawn(f, 'https://www.yahoo.com/'),
        gevent.spawn(f, 'https://github.com/'),
])
View Code

 总结:

要实现跨平台的多进程,可以使用multiprocessing模块。

进程间通信是通过Queue、pipes等实现的。 

线程是最小的执行单元,而进程由至少一个线程组成。如何调度进程和线程,完全由操作系统决定,程序自己不能决定什么时候执行,执行多久时间。

多进程和多线程的程序涉及到同步,数据共享的问题,编写起来更复杂。 

多线程编程,模型复杂,容易发生冲突,必须用锁加以隔离,同时,又要小心死锁发生。

Python解释器由于设计时有GIL全局锁,导致了多线程无法利用多核。多线程的并发在Python中就是一个美丽的梦。 

posted @ 2016-01-03 20:16  吴老二  阅读(492)  评论(0编辑  收藏  举报