0x00 环境
OS:WIN10
python:3.7
0x01 进程
1、进程
首先,在我们运行一个python代码时,操作系统会创建该程序的主进程:
import os
print("当前主进程pid : %s" % (os.getpid()))
2、子进程
在Windows中,通过multiprocessing的Process模块创建子进程,
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())
# 通过Process实例化创建一个子进程--p
p = Process(target=run_proc, args=('test',))
print('Child process will start.')
# 通过start()方法启动进程
p.start()
# 通过join()方法实现进程间的同步,即等待进程结束后再继续往下进行
p.join()
print('Child process end.')
Process模块的方法
方法名 | 作用 |
---|---|
start() | 启动进程,调用进程中的run()方法。 |
run() | 进程启动时运行的方法,正是它去调用target指定的函数,我们自定义类的类中一定要实现该方法 。 |
terminate() | 强制终止进程,不会进行任何清理操作。如果该进程终止前,创建了子进程,那么该子进程在其强制结束后变为僵尸进程;如果该进程还保存了一个锁那么也将不会被释放,进而导致死锁。使用时,要注意。 |
is_alive() | 判断某进程是否存活,存活返回True,否则False。 |
join([timeout]) | 主线程等待子线程终止。timeout为可选择超时时间;需要强调的是,p.join只能join住start开启的进程,而不能join住run开启的进程 。 |
daemon | 默认值为False,如果设置为True,代表该进程为后台守护进程;当该进程的父进程终止时,该进程也随之终止;并且设置为True后,该进程不能创建子进程,设置该属性必须在start()之前 |
name | 进程名称。 |
pid | 进程pid |
exitcode | 进程运行时为None,如果为-N,表示被信号N结束了。 |
authkey | 进程身份验证,默认是由os.urandom()随机生成32字符的字符串。这个键的用途是设计涉及网络连接的底层进程间的通信提供安全性,这类连接只有在具有相同身份验证才能成功。 |
0x02 多进程
import os
from time import sleep
from multiprocessing import Process
def hello(people):
sleep(1)
print(f"hello:\t{people}")
print(f"cunrent_process_id:\t{os.getpid()}")
sleep(1)
if __name__=='__main__':
peoples = ['people1','people2','people3','people4','people5','people6','people7','people8']
# 进程个数
maxprocess = 3
while peoples:
# 进程队列
process_list = []
for i in range(maxprocess):
if len(peoples) !=0 :
process_list.append(Process(target=hello,args=(peoples.pop(),)))
print("*"*50)
for i in process_list:
# 开启进程
i.start()
for i in process_list:
# 控制进程同步,意思就是每三个进程为一组,三个进程同步执行,每组进程间顺序执行,每组进程执行完毕才进入下一组
i.join()
0x03 进程池
若需要大量的子进程可通过multiprocessing的Pool模块创建进程池,
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())
# 由于Pool的默认大小是CPU的核数,如果你不幸拥有8核CPU,你要提交至少9个子进程才能看到上面的等待效果;8核可同时跑8个进程
p = Pool(4)
for i in range(5):
# apply_async非阻塞执行
p.apply_async(long_time_task, args=(i,))
print('Waiting for all subprocesses done...')
# 对Pool对象调用join()方法会等待所有子进程执行完毕,调用join()之前必须先调用close(),调用close()之后就不能继续添加新的Process了。
p.close()
p.join()
print('All subprocesses done.')
Pool模块属性方法:
方法 | 作用 |
---|---|
apply() | 该函数用于传递不定参数,主进程会被阻塞直到函数执行结束(不建议使用,并且3.x以后不在出现) |
apply_async | 与apply用法一致,但它是非阻塞的且支持结果返回后进行回调 |
map() | Pool类中的map方法,与内置的map函数用法基本一致,它会使进程阻塞直到结果返回 |
map_async() | 与map用法一致,但是它是非阻塞的。 |
close() | 关闭进程池(pool),使其不在接受新的任务。 |
terminal() | 结束工作进程,不在处理未处理的任务。 |
join() | 主进程阻塞等待子进程的退出, join方法要在close或terminate之后使用。 |
0x04 子进程
很多时候,子进程并不是自身,而是一个外部进程。我们创建进城后,还需要控制进程的输入和输出。
subprocess模块可以让我们非常方便地启动一个子进程,然后控制其输入和输出。
调用子进程执行系统命令“ping www.baidu.com”
import subprocess
print('$ ping www.baidu.com')
r = subprocess.call(['ping', 'www.baidu.com'])
print('Exit code:', r)
参考:https://www.liaoxuefeng.com/wiki/1016959663602400/1017628290184064
参考:https://www.shuopython.com/archives/2204