50 python使用进程 python进程的状态及创建 Python多线程和多进程的Join和daemon(守护)的用法
1树莓派有四个内核,但是使用线程实际上还是在一个核心。但是使用进程可以解决问题。
#方法一 直接调用 import time import random from multiprocessing import Process def run(name): print('%s runing' %name) time.sleep(random.randrange(1,5)) print('%s running end' %name) p1=Process(target=run,args=('anne',)) #必须加,号 p2=Process(target=run,args=('alice',)) p3=Process(target=run,args=('biantai',)) p4=Process(target=run,args=('haha',)) p1.deamon=True #伴随主进程关闭而关闭 p2.deamon=True p3.deamon=True p4.deamon=True p1.start() p2.start() p3.start() p4.start() print('主线程')
https://www.jianshu.com/p/7ac73e9c7150
运行和停止
要停止一个进程实例,可以调用方法terminate
:
p.terminate()
但是通过执行系统命令ps
查看停止后的进程, 你会发现, 直接调用terminate
方法停止的进程变成了一个僵尸进程(defunct), 只能等待主程序退出, 这个僵尸进程才会消失.
通过在terminate
后添加一次调用join
方法等待进程真正结束, 就能避免出现僵尸进程:
p.join()
程序
import time from multiprocessing import Process def run_forever(): while 1: print(time.time()) time.sleep(2) def main(): p = Process(target=run_forever) p.start() print('start a process.') time.sleep(10) if p.is_alive: # stop a process gracefully p.terminate() print('stop process') p.join() if __name__ == '__main__': main()
样例
双串口读取传感器数据给共享内存
# -*- coding: utf-8 -* import serial import time from multiprocessing import Process, Value, Array #读取温度和湿度 def serial_th(num,arr): ser = serial.Serial('/dev/ttyUSB1', 115200) if ser.isOpen == False: ser.open() # 打开串口 #ser.write(b"Raspberry pi is ready") try: while True: line = str(ser.readline()) fengefu='-' a=line.strip().split(fengefu) # x.strip()#除去每行的换行符 按照:分割 tv = "".join(a[1:2] ).strip() # 去除空格 hv = "".join(a[3:4]).strip() # 去除空格 arr[0]=int(tv) arr[1]=int(hv) #print('t-'+str(arr[0])+"-h-"+str(arr[1])) #time.sleep(0.1) # 软件延时 except KeyboardInterrupt: ser.close() #读取温度和湿度 def serial_lmq29(num,arr): ser = serial.Serial('/dev/ttyUSB0', 115200) if ser.isOpen == False: ser.open() # 打开串口 #ser.write(b"Raspberry pi is ready") try: while True: line = str(ser.readline()) fengefu='-' a=line.strip().split(fengefu) # x.strip()#除去每行的换行符 按照:分割 mq2 = "".join(a[1:2] ).strip() # 去除空格 light = "".join(a[3:4]).strip() # 去除空格 mq9 = "".join(a[5:6]).strip() # 去除空格 #print(mq9) arr[2]=int(mq2) arr[3]=int(light) arr[4]=int(mq9) #print('mq2-'+ str(arr[2]) +'-lihgt-'+str(arr[3])+'-mq9-'+str(arr[4])) #time.sleep(0.1) # 软件延时 except KeyboardInterrupt: ser.close() num_share = Value('d', 0.0) arr_share = Array('i', range(5)) p_wh = Process(target=serial_th, args=(num_share,arr_share)) p_wh.deamon=True #伴随主进程关闭而关闭 p_wh.start() p_l29 = Process(target=serial_lmq29, args=(num_share,arr_share)) p_l29.deamon=True p_l29.start() while 1: # 打印共享内存数据 print(arr_share[:])
进程通信 共享内存
https://docs.python.org/zh-cn/3/library/multiprocessing.html
共享内存
from multiprocessing import Process, Value, Array def f(n, a): n.value = 3.1415927 for i in range(len(a)): a[i] = -a[i] if __name__ == '__main__': num = Value('d', 0.0) arr = Array('i', range(10)) p = Process(target=f, args=(num, arr)) p.start() p.join() print(num.value) print(arr[:])
创建 num
和 arr
时使用的 'd'
和 'i'
参数是 array
模块使用的类型的 typecode : 'd'
表示双精度浮点数, 'i'
表示有符号整数。这些共享对象将是进程和线程安全的。
为了更灵活地使用共享内存,可以使用 multiprocessing.sharedctypes
模块,该模块支持创建从共享内存分配的任意ctypes对象。
给进程起名字
目标函数都是 foo()
函数。
# 命名一个进程 import multiprocessing import time def foo(): name = multiprocessing.current_process().name print("Starting %s " % name) time.sleep(3) print("Exiting %s " % name) if __name__ == '__main__': process_with_name = multiprocessing.Process(name='foo_process', target=foo) process_with_name.daemon = True # 注意原代码有这一行,但是译者发现删掉这一行才能得到正确输出 process_with_default_name = multiprocessing.Process(target=foo) process_with_name.start() process_with_default_name.start()
运行上面的代码,打开终端输入:
python naming_process.py
输出的结果如下:
$ python naming_process.py
Starting foo_process
Starting Process-2
Exiting foo_process
Exiting Process-2
https://blog.****.net/xlengji/article/details/81165370
关闭进程
https://blog.****.net/qq_28821995/article/details/82856217
首先,杀死进程的主要命令为ps,grep,kill这三个指令。
1、第一步是获取要监控进程的pid号:
def get_process_pid(name):
child = os.popen("ps -ef | grep "+name).readline()
response = child.split(' ')
print(response)
for i in range(2,20):
if response[i] != "":
pid_str = response[i]
print(i)
break
else:
pass
return pid_str
上面程序可以获取进程pid号,首先将得到的child进行分割,再循环监测去取进程pid号(name-要杀死的进程名称)
2、利用kill杀死进程:
pid = get_process_pid("xxx")
os.system('sudo kill -s 9'+pid)
ok! 杀死进程成功。
Python多线程和多进程的Join和daemon(守护)的用法
基本知识
下面仅以多线程为例:
首先需要明确几个概念:
知识点一:当一个进程启动之后,会默认产生一个主线程,因为线程是程序执行流的最小单元,当设置多线程时,主线程会创建多个子线程,在python中,默认情况下(其实就是setDaemon(False)),主线程执行完自己的任务以后,就退出了,此时子线程会继续执行自己的任务,直到自己的任务结束,例子见下面一。
知识点二:当我们使用setDaemon(True)方法,也就是设置子线程为守护线程时,主线程一旦执行结束,则全部线程全部被终止执行,可能出现的情况就是,子线程的任务还没有完全执行结束,就被迫停止,例子见下面二。
知识点三:此时join的作用就凸显出来了,join所完成的工作就是线程同步,即主线程任务结束之后,进入阻塞状态,一直等待其他的子线程执行结束之后,主线程再终止,例子见下面三。
知识点四:join有一个timeout参数:
当设置守护线程时,含义是主线程对于子线程等待timeout的时间将会杀死该子线程,最后退出程序。所以说,如果有10个子线程,全部的等待时间就是每个timeout的累加和。简单的来说,就是给每个子线程一个timeout的时间,让他去执行,时间一到,不管任务有没有完成,直接杀死。
没有设置守护线程时,主线程将会等待timeout的累加和这样的一段时间,时间一到,主线程结束,但是并没有杀死子线程,子线程依然可以继续执行,直到子线程全部结束,程序退出。
双串口