python命令分发器 event 怎么分发事件到不同进程

只需一步,快速开始
后使用快捷导航没有帐号?
查看: 1697|回复: 1
event | Pygame中文文档
签到天数: 1962 天[LV.Master]伴坛终老
马上注册加入鱼C,享用更多服务吧^_^
才可以下载或查看,没有帐号?
event | Pygame中文文档
pygame.event
用于处理事件与事件队列的 Pygame 模块。
pygame.event.pump()&&—&&让 Pygame 内部自动处理事件pygame.event.get()&&—&&从队列中获取事件pygame.event.poll()&&—&&从队列中获取一个事件pygame.event.wait()&&—&&等待并从队列中获取一个事件pygame.event.peek()&&—&&检测某类型事件是否在队列中pygame.event.clear()&&—&&从队列中删除所有的事件pygame.event.event_name()&&—&&通过 id 获得该事件的字符串名字pygame.event.set_blocked()&&—&&控制哪些事件禁止进入队列pygame.event.set_allowed()&&—&&控制哪些事件允许进入队列pygame.event.get_blocked()&&—&&检测某一类型的事件是否被禁止进入队列pygame.event.set_grab()&&—&&控制输入设备与其他应用程序的共享pygame.event.get_grab()&&—&&检测程序是否共享输入设备pygame.event.post()&&—&&放置一个新的事件到队列中pygame.event.Event()&&—&&创建一个新的事件对象pygame.event.EventType&&—&&代表 SDL 事件的 Pygame 对象
Pygame 通过事件队列控制所有的时间消息。该模块中的程序将帮你管理事件队列。输入队列很大程度依赖于 pygame 的
模块。如果 display 没有被初始化,显示模式没有被设置,那么事件队列就还没有开始真正工作。
常规的队列是由 pygame.event.EventType 定义的事件对象的组成,有多种方法来访问里边的事件对象:从简单的检测事件是否存在,到直接从栈中获取它们。
所有事件都有一个类型标识符,这个标识符对应的值定义在 NOEVENT 到 NUMEVENTS 之间(小甲鱼温馨提示:类似于 C 语言的宏定义,明白?)。用户可以自行定义事件,但类型标识符的值应该高于或等于 USEREVENT。
获取各种输入设备的状态,推荐你直接通过它们相应的模块(, 和 )提供的函数访问,而不是通过事件队列; 如果你使用此函数,请记住,Pygame 需要通过一些方式与系统的窗口管理器和平台的其他部分进行通信。为了保持 Pygame 和系统同步,你需要调用 pygame.event.pump() 确保实时更新,你将在游戏的每次循环中调用这个函数。
事件队列提供了一些简单的过滤。通过阻止某些事件进入事件队列,可以略微提高游戏的性能(小甲鱼温馨提示:因为这样事件队列的尺寸就会小一些,所以说可以略微提升性能)。使用 pygame.event.set_allowed() 和 pygame.event.set_blocked() 来控制某些事件是否允许进入事件队列。默认所有事件都会进入事件队列。
事件子系统应该在主线程被调用。如果你希望从其他线程中投递事件消息进入事件队列,请使用 fastevent 包。
Joysticks(游戏手柄)只有在设备初始化后才会发送事件。
一个 EventType 事件对象包含一个事件类型标识符和一组成员数据(事件对象不包含方法,只有数据)。EventType 对象从 Python 的事件队列中获得,你也可以使用 pygame.event.Event() 函数创建自定义的新事件。
由于 SDL 的事件队列限制了事件数量的上限(标准的 SDL 1.2 限制为 128),所以当队列已满时,新的事件将会被扔掉。为了防止丢失事件消息,尤其是代表退出的输入事件(因为当用户点击退出按钮没有反应,往往会被认为“死机”了),你的程序必须定期检测事件,并对其进行处理。
为了加快事件队列的处理速度,可以使用 pygame.event.set_blocked() 函数阻止一些我们不关注的事件进入队列中。
所有的 EventType 实例对象都拥有一个事件类型标识符,属性名是 type。你也可以通过事件对象的 __dict__ 属性来完全访问其他属性。所有其他成员属性的值都是通过事件对象的字典来传递。
在做调试和实验时,你可以打印事件对象以及相应的类型和成员。来自系统的事件都有一个事件类型和对应的成员属性,下边是每个事件类型以及对应的成员属性列表:
事件类型成员属性 QUIT none ACTIVEEVENT gain, state KEYDOWN unicode, key, mod KEYUP key, mod MOUSEMOTION pos, rel, buttons MOUSEBUTTONUP pos, button MOUSEBUTTONDOWN pos, button JOYAXISMOTION joy, axis, value JOYBALLMOTION joy, ball, rel JOYHATMOTION joy, hat, value JOYBUTTONUP joy, button JOYBUTTONDOWN joy, button VIDEORESIZE size, w, h VIDEOEXPOSE none USEREVENT code
事件支持等值比较。如果两个事件具有相同的类型和属性值,那么认为两个事件是相等的。(Pygame 1.9.2 新增加的)
pygame.event.pump()
让 Pygame 内部自动处理事件。
pump() -& None
对于游戏中的每一帧,你都需要通过某种形式去调用事件队列,这将确保你的程序在内部可以与操作系统的其他部分进行交互。如果你不打算使用其他事件函数,那么你应该调用 pygame.event.pump(),这将允许 Pygame 内部自动处理事件。
如果你的程序始终通过其他 event 模块的函数处理队列中的事件,那么该函数是没必要的。
事件队列中的内部处理是非常重要的事情。主窗口可能需要重新绘制或对系统做出响应。如果你太长时间没有调用事件队列,系统可能会认定你的程序已锁定(假死)。
pygame.event.get()
从队列中获取事件。
get() -& Eventlist
get(type) -& Eventlist
get(typelist) -& Eventlist
这将获取并从队列中删除事件。如果指定一个或多个 type 参数,那么只获取并删除指定类型的事件。
请注意,如果你只从队列中获取和删除指定的事件,那么久而久之,队列可能被你不关注的事件所填满。
pygame.event.poll()
从队列中获取一个事件。
poll() -& EventType instance
从队列中返回并删除一个事件。
如果事件队列为空,那么会立刻返回类型为 pygame.NOEVENT 的事件。
pygame.event.wait()
等待并从队列中获取一个事件。
wait() -& EventType instance
从队列中返回并删除一个事件。如果队列为空,那么该函数将持续等待直至队列中有一个事件。当程序在等待时,它将保持睡眠状态。这对于希望与其他应用程序共享系统来说,是非常重要的。
pygame.event.peek()
检测某类型事件是否在队列中。
peek(type) -& bool
peek(typelist) -& bool
如果参数指定的类型的事件存在于队列中,返回 True。
如果参数指定多个类型的事件,则只需队列中拥有其中的任何一个事件便返回 True。
pygame.event.clear()
从队列中删除所有的事件。
clear() -& None
clear(type) -& None
clear(typelist) -& None
从队列中删除所有的事件,如果通过参数指定事件的类型,则删除该类型的所有事件。该函数的效果跟 pygame.event.get() 相同,只是没有返回任何东西。当处理完关注的事件后,清空整个队列可以提高一些效率。
pygame.event.event_name()
通过 id 获得该事件的字符串名字。
event_name(type) -& string
Pygame 通过整数 id 代表事件类型。如果你需要将这些类型的事件展示给用户看,那么你需要将它们转换成字符串(一堆数字谁知道你想表示啥?)。该函数将返回事件类型对应的字符串名字。返回值是以单词大写的样式(小甲鱼温馨提示:DanCiDaXieDe)。
pygame.event.set_blocked()
控制哪些事件禁止进入队列。
set_blocked(type) -& None
set_blocked(typelist) -& None
set_blocked(None) -& None
参数指定的类型的事件均不允许出现在事件队列中。默认是允许所有事件进入队列。多次禁止同一类型的事件并不会引发什么问题。
如果传入 None,则表示允许所有的事件进入队列。
pygame.event.set_allowed()
控制哪些事件允许进入队列。
set_allowed(type) -& None
set_allowed(typelist) -& None
set_allowed(None) -& None
参数指定的类型的事件均允许出现在事件队列中。默认是允许所有事件进入队列。多次允许同一类型的事件并不会引发什么问题。
如果传入 None,则表示禁止所有的事件进入队列。
pygame.event.get_blocked()
检测某一类型的事件是否被禁止进入队列。
get_blocked(type) -& bool
如果参数指定类型的事件被禁止进入队列,则返回 True。
pygame.event.set_grab()
控制输入设备与其他应用程序的共享。
set_grab(bool) -& None
当你的程序运行在窗口环境中,它将与其他拥有焦点的应用程序分享鼠标和键盘设备的输入。如果你的程序设置事件独占为 True,那么你的程序将锁定所有的输入(小甲鱼温馨提示:不共享给其他程序了)。
最好不要经常独占输入,因为这将阻止用户在操作系统上的其他操作。
pygame.event.get_grab()
检测程序是否共享输入设备。
get_grab() -& bool
当程序独占输入事件时,返回 True。使用 pygame.event.set_grab() 函数控制这一状态。
pygame.event.post()
放置一个新的事件到队列中。
post(Event) -& None
该函数将放置一个新的事件到事件队列的末端。这些事件将最迟被其他队列函数获取。
该函数通常用于放置 pygame.USEREVENT(用户自定义事件)事件到队列中。尽管你可以放置所有类型的事件,但你需要确保为系统事件类型相应的属性传递合适的值。
如果 SDL 事件队列已满,将抛出 pygame.error 异常。
pygame.event.Event()
创建一个新的事件对象。
Event(type, dict) -& EventType instance
Event(type, **attributes) -& EventType instance
根据参数给定的类型创建一个新的事件。dict 参数指定事件的属性以及相应的值。
class pygame.event.EventType
代表 SDL 事件的 Pygame 对象。
pygame.event.EventType.type&&—&&SDL event type identifier.
pygame.event.EventType.__dict__&&—&&vent object attribute dictionary
用于代表 SDL 事件的 Pygame 对象。通过 pygame.event.Event() 创建用户自定义事件。EventType 类型并不是直接可以被调用的。EventType 实例对象支持属性赋值和删除。
SDL 事件类型标识符。
type -& int
只读。预定义事件标识符是 QUIT 和 MOUSEMOTION 等。对于用于创建的事件对象,这是传递给 pygame.event.Event() 的 type 参数。
事件对象的属性字典。
__dict__ -& dict
只读。事件类型指定的属性。例如,KEYDOWN 事件包含 unicode,key 和 mod 属性。
可变属性是 Pygame 1.9.2 新增加的。
如果您的【问题求助】得到满意的解答,请自行将分类修改为【已经解决】;如果想鼓励一下楼主或帮助到您的朋友,可以给他们【评分】鼓励;善用【论坛搜索】功能,那里可能有您想要的答案!
签到天数: 67 天[LV.6]常住居民II
From FishC Mobile
如果您的【问题求助】得到满意的解答,请自行将分类修改为【已经解决】;如果想鼓励一下楼主或帮助到您的朋友,可以给他们【评分】鼓励;善用【论坛搜索】功能,那里可能有您想要的答案!
•••(
Powered by4025人阅读
python(1)
最近用python写一个网络服务的模拟测试程序,先是用同步socket实现了一个简单的server,后来发现要没法添加定时器来定时处理一些任务,于是网上搜索python的异步事件框架库,发现了gevent。
1. gevent介绍
gevent是一个python的网络库,它使用greenlet轻量级线程,使用libevent实现事件驱动。我写的模拟测试程序只使用了libevent的事件驱动,下面就只介绍下gevent的事件驱动编程。
2. 事件驱动
事件驱动顾名思义,就是通过事件来驱动程序的运行,它主要包括三个部分:事件,事件处理,事件分发。gevent是事件驱动是对libevent的封装,因此它关于上述三个部分的描述也类似于libevent。
gevent的事件驱动处理都在gevent.core模块,主要包含以下类:
event(事件)
class&gevent.core.event(evtype,&handle,&callback[,&arg])
使用callback事件处理回调函数创建一个事件对象。
evtype - 事件类型,EV_READ or EV_WRITE, or EV_SIGNAL
handle - 事件句柄,对于EV_READ和EV_WRITE来说handle是一个socket, 对于EV_SIGNAL来说就是一个信号值
callback - 事件发生时回调该函数来对事件进行处理
arg - 可选参数
add([timeout])
调用该方法将事件添加到事件调度器,该函数有一个可选的timeout参数,以秒为单位。设置了该参数后事件timout秒后将被执行。
取消事件的调度。
事件的属性,如果事件仍然在事件调度器中等候调度将返回True。
class&gevent.core.read_event
&创建一个类型为EV_READ的事件
class&gevent.core.write_event
&创建一个类型为EV_READ的事件
class&gevent.core.timer
创建一个定时器
class&gevent.core.signal
&创建一个信号事件
event loop
gevent.core.init()
初始化事件队列
gevent.core.dispatch()
分发事件队列中所有的事件,成功返回0,当没有事件注册时返回1.
gevent.core.loop()
分发队列中所有待处理的事件,只执行一次。成功返回0,没有事件注册时返回1。该函数与dispatch的区别是该函数单趟执行。
3. 开发流程
1. gevent.core.init()
2. 创建事件
3. 添加事件
4. gevent.core.loop()
4. 程序示例
使用gevent实现的echo,同时有一个定时器
from gevent import core
from socket import *
from sys import *
class mon_client_handler:
def __init__(self, s_fd, addr ):
self.s_fd = s_fd
self.addr = addr
self.r_ev = core.read_event( self.s_fd.fileno(), self.on_read )
self.w_ev = core.write_event( self.s_fd.fileno(), self.on_write )
self.t_ev = core.timer( -1, self.on_timeout )
self.r_buffer = ''
self.w_buffer = ''
def on_read(self, ev, ev_type ):
#print 'on_read'
#print self.addr
chunk = self.s_fd.recv(1024)
print 'read chunk len:', len(chunk)
self.r_buffer += chunk
#print 'buffer len:', len(self.r_buffer)
self.process()
self.r_ev.add()
def on_write(self, ev, ev_type ):
#print self,ev,ev_type
if len(self.w_buffer) & 0:
size = self.s_fd.send(self.w_buffer)
print len(self.w_buffer), size
self.w_buffer = self.w_buffer[size:]
if len(self.w_buffer) & 0:
self.w_ev.add()
def write(self, buf):
#print 'write', len(buf)
self.w_buffer += buf
if len(self.w_buffer) & 0:
self.w_ev.add()
def start(self):
self.r_ev.add()
self.t_ev.add(10)
def stop(self):
self.r_ev.cancel()
self.w_ev.cancel()
self.t_ev.cancel()
self.s_fd.close()
def process(self):
self.write(self.r_buffer)
self.r_buffer=''
def on_timeout(self):
print 'timeout...'
self.t_ev.add(5)
class mon_server:
def __init__(self, port, max_clt):
self.port = port
self.max_clt = max_clt
self.fd = None
self.event = None
self.started = False
def start(self):
if self.started:
print 'mon_server alread started!'
return False
self.fd = socket(AF_INET, SOCK_STREAM)
self.fd.bind(('0.0.0.0', self.port))
self.fd.setblocking(0)
self.event = core.read_event( self.fd.fileno(), self.on_request )
self.event.add()
self.fd.listen(self.max_clt)
self.clients = []
return True
def stop(self):
self.event.cancel()
self.fd.close()
def on_request( self, e, evtype ):
(clt_fd, addr) = self.fd.accept()
clt_fd.setblocking(0)
print 'Connected by', addr
clt = mon_client_handler( clt_fd, addr )
self.clients.append(clt)
clt.start()
def main():
core.init()
svr = mon_server( 8888, 1 )
svr.start()
core.dispatch()
print 'Server exit!'
if __name__ == '__main__':
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:47854次
排名:千里之外
原创:25篇
转载:10篇
评论:14条
(1)(2)(2)(3)(1)(6)(6)(1)(2)(3)(9)(2)qw87112 的BLOG
用户名:qw87112
文章数:98
评论数:41
访问量:53314
注册日期:
阅读量:5863
阅读量:12276
阅读量:379382
阅读量:1071837
51CTO推荐博文
我们先来了解什么是进程?程序并不能单独运行,只有将程序装载到内存中,系统为它分配资源才能运行,而这种执行的程序就称之为进程。程序和进程的区别就在于:程序是指令的集合,它是进程运行的静态描述文本;进程是程序的一次执行活动,属于动态概念。在多道编程中,我们允许多个程序同时加载到内存中,在操作系统的调度下,可以实现并发地执行。这是这样的设计,大大提高了CPU的利用率。进程的出现让每个用户感觉到自己独享CPU,因此,进程就是为了在CPU上实现多道编程而提出的。有了进程为什么还要线程?进程提供了多道编程,充分发挥了计算机部件的并行性,提高了计算机的利用率,既然进程这么优秀,为什么还要线程呢?&其实,还是有很多缺陷的,主要体现在两点上:进程只能在一个时间干一件事,如果想同时干两件事或多件事,进程就无能为力了。进程在执行的过程中如果阻塞,例如等待输入,整个进程就会挂起,即使进程中有些工作不依赖于输入的数据,也将无法执行。而解决办法就是让单个进程,接受请求、等待I/O、处理计算并行起来,这样很明显可以避免同步等待,提高执行效率,在实际操作系统中这样的机制就是――线程。线程的优点因为要并发,我们发明了进程,又进一步发明了线程。只不过进程和线程的并发层次不同:进程属于在处理器这一层上提供的抽象;线程则属于在进程这个层次上再提供了一层并发的抽象。如果我们进入计算机体系结构里,就会发现,流水线提供的也是一种并发,不过是指令级的并发。这样,流水线、线程、进程就从低到高在三个层次上提供我们所迫切需要的并发!除了提高进程的并发度,线程还有个好处,就是可以有效地利用多处理器和多核计算机。现在的处理器有个趋势就是朝着多核方向发展,在没有线程之前,多核并不能让一个进程的执行速度提高,原因还是上面所有的两点限制。但如果讲一个进程分解为若干个线程,则可以让不同的线程运行在不同的核上,从而提高了进程的执行速度。例如:我们经常使用微软的Word进行文字排版,实际上就打开了多个线程。这些线程一个负责显示,一个接受键盘的输入,一个进行存盘等等。这些线程一起运行,让我们感觉到我们输入和屏幕显示同时发生,而不是输入一些字符,过一段时间才能看到显示出来。在我们不经意间,还进行了自动存盘操作。这就是线程给我们带来的方便之处。进程与线程的区别进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位。线程是进程的一个实体,&是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源。一个线程可以创建和撤销另一个线程,同一个进程中的多个线程之间可以并发执行。进程和线程的主要差别在于它们是不同的操作系统资源管理方式。进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个线程死掉就等于整个进程死掉,所以多进程的程序要比多线程的程序 健壮,但在进程切换时,耗费资源较大,效率要差一些。但对于一些要求同时进行并且又要共享某些变量的并发操作,只能用线程,不能用进程。Python 多进程(multiprocessing)Unix/Linux操作系统提供了一个fork()系统调用,它非常特殊。普通的函数调用,调用一次,返回一次,但是fork()调用一次,返回两次,因为操作系统自动把当前进程(称为父进程)复制了一份(称为子进程),然后,分别在父进程和子进程内返回。子进程永远返回0,而父进程返回子进程的ID。这样做的理由是,一个父进程可以fork出很多子进程,所以,父进程要记下每个子进程的ID,而子进程只需要调用getppid()就可以拿到父进程的ID。Python的os模块封装了常见的系统调用,其中就包括fork,可以在Python程序中轻松创建子进程:#&multiprocessing.py
print&'Process&(%s)&start...'&%&os.getpid()
pid&=&os.fork()
if&pid==0:
&&&&print&'I&am&child&process&(%s)&and&my&parent&is&%s.'&%&(os.getpid(),&os.getppid())
&&&&print&'I&(%s)&just&created&a&child&process&(%s).'&%&(os.getpid(),&pid)由于Windows没有fork调用,上面的代码在Windows上无法运行。multiprocessingmultiprocessing是跨平台版本的多进程模块,它提供了一个Process类来代表一个进程对象,下面是示例代码:#!/usr/local/python27/bin/python2.7
#&coding=utf8
#&noinspection&PyUnresolvedReferences
from&multiprocessing&import&Process
import&time
&&&&time.sleep(1)
&&&&print&n*n
for&i&in&range(10):
&&&&p&=&Process(target=f,args=[i,])
&&&&p.start()这个程序如果用单进程写则需要执行10秒以上的时间,而用多进程则启动10个进程并行执行,只需要用1秒多的时间。在一般情况下多个进程的内存资源是相互独立的,而多线程可以共享同一个进程中的内存资源,示例代码:#!/usr/local/python27/bin/python2.7
#&coding=utf8
#&noinspection&PyUnresolvedReferences
#&通过多进程和多线程对比,进程间内存无法共享,线程间的内存共享
from&multiprocessing&import&Process
import&threading
import&time
lock&=&threading.Lock()
def&run(info_list,n):
&&&&lock.acquire()
&&&&info_list.append(n)
&&&&lock.release()
&&&&print('%s\n'&%&info_list)
for&i&in&range(10):
'''target为子进程执行的函数,args为需要给函数传递的参数'''&&&&
&&&&p&=&Process(target=run,args=[info,i])
&&&&p.start()
'''这里是为了输出整齐让主进程的执行等一下子进程'''&&&&
time.sleep(1)&&&&
print('------------threading--------------')
for&i&in&range(10):
&&&&p&=&threading.Thread(target=run,args=[info,i])
&&&&p.start()执行结果:进程间通信QueueQueue是多进程安全的队列,可以使用Queue实现多进程之间的数据传递。put方法用以插入数据到队列中,put方法还有两个可选参数:blocked和timeout。如果blocked为True(默认值),并且timeout为正值,该方法会阻塞timeout指定的时间,直到该队列有剩余的空间。如果超时,会抛出Queue.Full异常。如果blocked为False,但该Queue已满,会立即抛出Queue.Full异常。&get方法可以从队列读取并且删除一个元素。同样,get方法有两个可选参数:blocked和timeout。如果blocked为True(默认值),并且timeout为正值,那么在等待时间内没有取到任何元素,会抛出Queue.Empty异常。如果blocked为False,有两种情况存在,如果Queue有一个值可用,则立即返回该值,否则,如果队列为空,则立即抛出Queue.Empty异常。Queue的一段示例代码:#!/usr/local/python27/bin/python2.7
#&coding=utf8
#&noinspection&PyUnresolvedReferences
#&通过multiprocessing.Queue实现进程间内存共享
from&multiprocessing&import&Process,Queue
import&time
def&write(q):
&&&&for&i&in&['A','B','C','D','E']:
&&&&&&&&print('Put&%s&to&queue'&%&i)
&&&&&&&&q.put(i)
&&&&&&&&time.sleep(0.5)
def&read(q):
&&&&while&True:
&&&&&&&&v&=&q.get(True)
&&&&&&&&print('get&%s&from&queue'&%v)
if&__name__&==&'__main__':
&&&&q&=&Queue()
&&&&pw&=&Process(target=write,args=(q,))
&&&&pr&=&Process(target=read,args=(q,))
&&&&pw.start()
&&&&pr.start()
&&&&pr.join()
&&&&pr.terminate()执行结果:Value,Array#!/usr/local/python27/bin/python2.7
#&coding=utf8
#&noinspection&PyUnresolvedReferences
#&通过Value&Array&实现进程间的内存共享
from&multiprocessing&import&Value,Array,Process
def&f(n,a,raw):
&&&&n.value&=&3.14
&&&&for&i&in&range(5):
&&&&&&&&a[i]&=&-a[i]
&&&&raw.append(9999)
&&&&print(raw)
if&__name__&==&'__main__':
&&&&num&=&Value('d',0.0)
&&&&arr&=&Array('i',range(10))
&&&&raw_list&=&range(10)
&&&&print(num.value)
&&&&print(arr[:])
&&&&print(raw_list)
#调用子进程之后,重新打印array和value,值将会发生改变。&而raw_list&普通列表在外层打印则没有发生改变。
&&&&p&=&Process(target=f,args=(num,arr,raw_list))
&&&&p.start()
&&&&p.join()
&&&&print(num.value)
&&&&print(arr[:])
&&&&print(raw_list)执行结果:Manager&#!/usr/local/python27/bin/python2.7
#&coding=utf8
#&noinspection&PyUnresolvedReferences
from&multiprocessing&import&Process,Manager
def&f(d,l):
&&&&d[1]&=&'1'
&&&&d['aa']&=&'hello&World'
&&&&l.reverse()
if&__name__&==&'__main__':
&&&&manager&=&Manager()
&&&&d&=&manager.dict()
&&&&l&=&manager.list(range(10))
&&&&p&=&Process(target=f,args=(d,l))
&&&&p.start()
&&&&p.join()
&&&&print(d)
&&&&print(l)执行结果:Pool (进程池)用于批量创建子进程,可以灵活控制子进程的数量#!/usr/local/python27/bin/python2.7
#&coding=utf8
#&noinspection&PyUnresolvedReferences
from&multiprocessing&import&Pool
import&time
&&&&print&x*x
&&&&time.sleep(2)
&&&&return&x*x
'''定义启动的进程数量'''
pool&=&Pool(processes=5)
res_list&=&[]
for&i&in&range(10):
&&&&'''以异步并行的方式启动进程,如果要同步等待的方式,可以在每次启动进程之后调用res.get()方法,也可以使用Pool.apply'''
&&&&res&=&pool.apply_async(f,[i,])
&&&&print('-------:',i)
&&&&res_list.append(res)
pool.close()
pool.join()
for&r&in&res_list:
&&&&print(r.get(timeout=5))Pool对象调用join()方法会等待所有子进程执行完毕,调用join()之前必须先调用close(),调用close()之后就不能继续添加新的Process了。Python 多线程(threading)上面介绍了线程的作用,在python的标准库中提供了两个模块:thread和threading,threading是对thread进行了封装的高级模块。启动一个线程就是把一个函数传给Thread实例,然后调用start()方法。&先来看一个示例程序:#!/usr/local/python27/bin/python2.7
#&coding=utf8
#&noinspection&PyUnresolvedReferences
from&threading&import&Thread
import&time
&&&&time.sleep(1)
&&&&num&=&n*n
&&&&print('%s\n'&%&num)
l1&=&range(10)
for&i&in&l1:
&&&&p&=&Thread(target=f,args=(i,))
&&&&p.start()Lock多线程和多进程最大的不同在于,多进程中,同一个变量,各自有一份拷贝存在于每个进程中,互不影响,而多线程中,所有变量都由所有线程共享,所以,任何一个变量都可以被任何一个线程修改,因此,线程之间共享数据最大的危险在于多个线程同时改一个变量,把内容给改乱了。示例代码:#!/usr/local/python27/bin/python2.7
#&coding=utf8
#&noinspection&PyUnresolvedReferences
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()
print&balance定义的这个balance最后执行结果理论上是0,但是多个线程交替执行时就不一定是0了,因为修改balance需要多条语句,而执行这几条语句时,线程可能中断,从而导致多个线程把同一个对象的内容改乱了。两个线程同时一存一取,就可能导致数据不对,如果要确保balance计算正确,就需要给change_i()上一把锁,确保一个线程在修改balance的时候,别的线程一定不能改。下面看示例代码,创建锁通过threading.Lock()来实现:#!/usr/local/python27/bin/python2.7
#&coding=utf8
#&noinspection&PyUnresolvedReferences
import&time,&threading
balance&=&0
lock&=&threading.Lock()
def&change_it(n):
&&&&#&先加后减,结果应该为0:
&&&&global&balance
&&&&balance&=&balance&+&n
&&&&balance&=&balance&-&n
def&run_thread(n):
&&&&for&i&in&range(100000):
&&&&&&&&lock.acquire()
&&&&&&&&try:
&&&&&&&&&&&&change_it(n)
&&&&&&&&finally:
&&&&&&&&&&&&lock.release()
t1&=&threading.Thread(target=run_thread,&args=(5,))
t2&=&threading.Thread(target=run_thread,&args=(8,))
t1.start()
t2.start()
print&balance生产者消费者模型#!/usr/local/python27/bin/python2.7
#&coding=utf8
#&noinspection&PyUnresolvedReferences
from&threading&import&Thread
from&Queue&import&Queue
import&time
class&procuder(Thread):
&&&&@:param&name:生产者名称
&&&&@:param&queue:容器
&&&&def&__init__(self,name,queue):
&&&&&&&&self.__Name&=&name
&&&&&&&&self.__Queue&=&queue
&&&&&&&&super(procuder,self).__init__()
&&&&def&run(self):
&&&&&&&&while&True:
&&&&&&&&&&&&if&self.__Queue.full():
&&&&&&&&&&&&&&&&time.sleep(1)
&&&&&&&&&&&&else:
&&&&&&&&&&&&&&&&self.__Queue.put('baozi')
&&&&&&&&&&&&&&&&time.sleep(1)
&&&&&&&&&&&&&&&&print('%s&生产了一个包子'&%(self.__Name))
class&consumer(Thread):
&&&&def&__init__(self,name,queue):
&&&&&&&&self.__Name&=&name
&&&&&&&&self.__Queue&=&queue
&&&&&&&&'''执行父类的构造方法'''
&&&&&&&&super(consumer,self).__init__()
&&&&def&run(self):
&&&&&&&&while&True:
&&&&&&&&&&&&if&self.__Queue.empty():
&&&&&&&&&&&&&&&&time.sleep(1)
&&&&&&&&&&&&else:
&&&&&&&&&&&&&&&&self.__Queue.get()
&&&&&&&&&&&&&&&&time.sleep(1)
&&&&&&&&&&&&&&&&print('%s&吃了一个包子'&%(self.__Name))
que&=&Queue(maxsize=100)
tuchao1&=&procuder('小涂1',que)
tuchao1.start()
tuchao2&=&procuder('小涂2',que)
tuchao2.start()
tuchao3&=&procuder('小涂3',que)
tuchao3.start()
for&i&in&range(20):
&&&&name&=&'小喻%d'&%(i,)
&&&&temp&=&consumer(name,que)
&&&&temp.start()python 多线程开发之事件#!/usr/local/python27/bin/python2.7
#&coding=utf8
#&noinspection&PyUnresolvedReferences
import&threading
import&time
def&producer():
&&&&print&('店家:本店出售包子。。。。')
&&&&'''触发事务等待'''
&&&&event.wait()
&&&&'''清楚事务状态'''
&&&&event.clear()
&&&&print&('小明:老板,请给我一个肉包子。。。。')
&&&&print&('店家:正在生产包子,请稍等xxxxxxxxx')
&&&&time.sleep(6)
&&&&print&('店家:你要的包子已经好了------')
&&&&event.set()
def&consumer():
&&&&print('小明去买包子。。。。')
&&&&'''解除事务等待'''
&&&&event.set()
&&&&time.sleep(2)
&&&&while&True:
&&&&&&&&if&event.isSet():
&&&&&&&&&&&&print&('谢谢!')
&&&&&&&&&&&&break
&&&&&&&&else:
&&&&&&&&&&&&print&('包子还没好吗?&等待中...')
&&&&&&&&&&&&time.sleep(1)
event&=&threading.Event()
p&=&threading.Thread(target=producer)
c&=&threading.Thread(target=consumer)
p.start()执行结果:GIL锁(Global Interpreter Lock)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锁,互不影响。参考文献:/hazir/archive//2447287.html本文出自 “” 博客,请务必保留此出处
了这篇文章
类别:未分类┆阅读(0)┆评论(0)
01:40:26 17:04:11 15:00:31

我要回帖

更多关于 python 命令分发 的文章

 

随机推荐