python的系统工具os与sys中与进程之间几个函数的调用

1.使用简单的共享全局数据 在父/主线程中探知线程何时结束 线程共享列表但是不共享列表里的对象 假设列表在内存中创建后不会移动

>>> import _thread as thread
>>> stdoutmutex=thread.allocate_lock()
>>> exitmutexes=[False]*10
>>> def counter(myId,count):
	for i in range(count):
		stdoutmutex.acquire()
		print('[%s]=>%s'%(myId,i))
		stdoutmutex.release()
	exitmutexes[myId]=True #向主线程发送信号

	
>>> for i in range(10):
	thread.start_new_thread(counter,(i,12))

运行结果 :
123145488994304[0]=>0

123145505783808[0]=>1

123145522573312[0]=>2

123145539362816[0]=>3

123145556152320[0]=>4

123145572941824[0]=>5

123145589731328[0]=>6

123145606520832[0]=>7

123145623310336[0]=>8

123145640099840[0]=>9

[0]=>10
[0]=>11
[2]=>0
[2]=>1
[2]=>2
[2]=>3
[2]=>4
[2]=>5
[2]=>6
[2]=>7
[2]=>8
[2]=>9
[2]=>10
[2]=>11
[1]=>0
[1]=>1
[1]=>2
[1]=>3
[1]=>4
[1]=>5
[1]=>6
[1]=>7
[1]=>8
[1]=>9
[1]=>10
[1]=>11
[7]=>0
[7]=>1
[7]=>2
[7]=>3
[7]=>4
[7]=>5
[7]=>6
[7]=>7
[7]=>8
[7]=>9
[7]=>10
[7]=>11
[6]=>0
[6]=>1
[6]=>2
[6]=>3
[6]=>4
[6]=>5
[6]=>6
[6]=>7
[6]=>8
[6]=>9
[6]=>10
[6]=>11
[8]=>0
[8]=>1
[8]=>2
[8]=>3
[8]=>4
[8]=>5
[8]=>6
[8]=>7
[8]=>8
[8]=>9
[8]=>10
[8]=>11
[4]=>0
[4]=>1
[4]=>2
[4]=>3
[4]=>4
[4]=>5
[4]=>6
[4]=>7
[4]=>8
[4]=>9
[4]=>10
[4]=>11
[3]=>0
[3]=>1
[3]=>2
[3]=>3
[3]=>4
[3]=>5
[3]=>6
[3]=>7
[3]=>8
[3]=>9
[3]=>10
[3]=>11
[5]=>0
[5]=>1
[5]=>2
[5]=>3
[5]=>4
[5]=>5
[5]=>6
[5]=>7
[5]=>8
[5]=>9
[5]=>10
[5]=>11
[9]=>0
[9]=>1
[9]=>2
[9]=>3
[9]=>4
[9]=>5
[9]=>6
[9]=>7
[9]=>8
[9]=>9
[9]=>10
[9]=>11

添加休眠时间:

>>> import _thread as thread,time
>>> stdoutmutex=thread.allocate_lock()
>>> numthreads=5
>>> exitmutexes=[thread.allocate_lock() for i in range(numthreads)]
>>> def counter(myId,count,mutex):
	for i in range(count):
		time.sleep(1/(myId+1))
		with mutex:
			print('[%s]=>%s'%(myId,i))
	exitmutexes[myId].acquire()
>>> for i in range(numthreads):
	thread.start_new_thread(counter,(i,5,stdoutmutex))

多了视觉延迟的效果.

2.threading模块
Python标准库带有两个线程模块:_thread,此前一直介绍的较低层面上的基本接口;threading,基于对象和类的较高层面的上的接口.threading模块在内部使用_thread模块来实现线程的对象以及常见同步化工具的功能.这个模块是松散地基于java语言中的threading模型中的一个子集,不过只有java程序员可以察觉到方式差异。
带有状态和run()行为的线程类实例,使用较高层面上的类java的threading模块对象连接方法在主线程中探知线程结束时间。

>>> import threading
>>> class Mythread(threading.Thread):  #子类的Thread对象
	def __init__(self,myId,count,mutex):
		self.myId=myId
		self.count=count    #各个线程状态信息
		self.mutex=mutex   #共享对象,不是全局对象
		threading.Thread.__init__(self)
	def run(self):         #run函数提供线程逻辑业务
		for i in range(self.count):  #同步化stdout访问
			with self.mutex:
				print('[%s]=>%s'%(self.myId,i))
>>> stdoutmutex=threading.Lock() #与thread.allocate_lock()相同
>>> threads=[]
>>> for i in range(10):
	thread=Mythread(i,12,stdoutmutex)   #创建开始10个线程
	thread.start()
	threads.append(thread)

线程在运行时间上是随机分布的.

接下来是设置生产者与消费者线程与共享队列进行通信:

>>> numconsumers=2
>>> numproduces=4
>>> nummessage=4
>>> import _thread as thread,queue,time
>>> safeprint=thread.allocate_lock()
>>> dataQueue=queue.Queue()
>>> def producer(idnum):
	for msgnum in range(nummessages):
		time.sleep(idnum)
		dataQueue.put('[producer id=%d,count=%d]'%(idnum,msgnum))
>>> def consumer(idnum):
	while True:
		time.sleep(0.1)
		try:
			data=dataQueue.get(block=False)
		except queue.Empty:
			pass
		else:
			with safeprint:
				print('consumer',idnum,'got=>',data)
>>> if __name__=='__main__':
	for i in range(numconsumers):
		thread.start_new_thread(consumer,(i,))
	for i in range(numproducers):
		thread.start_new_thread(producer,(i,))
	time.sleep(((numproducers-1)*nummessages)+1)
	print('Main thread exit.')

在此请注意队列是如何给一个全局变量赋值的.因为这一点,它可以在所有派生的线程中共享.因为这些线程改变对象而非变量名,所以队列对象作为参数传入线程中的函数也是可行的.队列是内存中的共享对象,无论采用是何种方式:

>>> dataQueue=queue.Queue()
>>> def producer(idnum,dataqueue):
	for msgnum in range(nummessages):
		time.sleep(dinum)
		dataqueue.put('[producer id=%d,count=%d]'%(idnum,msgnum))
>>> def consumer(idnum,dataqueue):...
>>> numproducers=4
>>> if __name__=='__main__':
	for i in range(numproducers):
		thread.start_new_thread(producer,(i,dataQueue))
	for i in range(numproducers):
		thread.start_new_thread(producer,(i,dataQueue))

守护线程与退出:

>>> import threading,queue,time
>>> def producer(idnum,dataqueue):...
>>> def consumer(idnum,dataqueue):...
>>> if __name__=='__main__':
	for i in range(numconsumers):
		thread=threading.Thread(target=consumer,args=(i,dataQueue))
		thread.daemon=True
		thread.start()
	waitfor=[]
	for i in range(numproducers):
		thread=threading.Thread(target=producer,args=(i,dataQueue))
		waitfor.append(thread)
		thread.start()
	for thread in waitfor:thread.join()
	print('Main thread exit.')

运行此脚本,可以试着调整脚本开头部分的参数试验不同的情景.

关于退出:
内建的sys.exit()函数在调用时可以让程序提前结束:
有意思的是,这个函数其实只抛出了一个内建的SystemExit异常.因此,我们可以像往常那样捕获这个异常,来拦截程序的过早退出并执行清理活动;如果未被捕获,则解释器正常退出.

>>> try:
	sys.exit()
except SystemExit:
	print('ignoring exit')
ignoring exit

上面代码俗称(钩子),防止意外关闭,毕竟是try…except…异常捕获语句程序.

下面的码表示了如何从进程中的函数里面退出:

>>> def later():
	import sys
	print('Bye sys world')
	sys.exit(42)
	print('Never reched')
>>> if __name__=='__main__':later()
Bye sys world

然后将上面代码保存为.py的文件,载入这个函数的程序可以将其退出异常捕获并且重写,或者编写一个负责清理的finally代码块,用于在程序退出处理时运行:
第一段:

>>> from testexit_sys import later #将上一段代码保存.py文件然后放到你的编译运行的正确目录下
>>> try:
	later()
except SystemExit:
	print('Ignored...')
Bye sys world
Ignored...

第二段:

>>> try:
	later()
finally:
	print('Cleanup')
Bye sys world
Cleanup

然后显示交互式会话进程的退出

接下来是os版本的退出模式,首先把os函数define一下:

def outahere():
	import os
	prinyt('out of os world')
	os._exit(88)
	print('Never reached')
>>> if __name__=='__main__':outahere()

第一次调用:

>>> from testexit_os import outahere
>>> try:
	outahere()
except:
	print('Ignored')
Ignored

第二次调用:

>>> from testexit_os import outahere
>>> try:
	outahere()
finally:
	print('Cleanup')
Cleanup

和sys.exit不同,try/except和try/finally截获对os._exit均不起作用.
下面在Linux系统下用os.system和os.Popen获得退出状态,我们先看一个shell命令的实例.下面的例子在Linux上运行通过管道读取输出流并获取他们的退出状态代码:

>>> import os
>>> pipe=os.popen('python testexit_sys.py')
>>> pipe.read()
''
>>> stat=pipe.close()
>>> stat
512
>>> hex=(stat)
>>> stat>>8
2
>>> pipe=os.popen('python testexit_os.py')
>>> stat=pipe.close()
>>> stat,stat >>8
(512, 2)

此类代码在Windows,mac os x,linux三大操作系统中均可运行.由于在内存中的地址差异可能导致输出的状态代码略有差异.退出状态不在位掩码中编码,此外还可以用sys.platform.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

GOD FOR JAVA

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值