import threading import time def tstart(arg): print("%s running....at: %s" % (arg,time.time())) time.sleep(1) print("%s is finished! at: %s" % (arg,time.time())) if __name__ == '__main__': t1 = threading.Thread(target=tstart, args=('This is thread 1',)) t1.setDaemon(True) t1.start() # t1.join() # 当前线程阻塞,等待t1线程执行完成 print("This is main function at:%s" % time.time())
结果:
This is thread 1 running....at: 1564906847.85 This is main function at:1564906847.85
python多进程相比较于threading模块用于创建python多线程,python提供multiprocessing用于创建多进程。先看一下创建进程的两种方式。
The multiprocessing package mostly replicates the API of the threading module. —— python doc
创建进程
创建进程的方式和创建线程的方式类似:
实例化一个multiprocessing.Process的对象,并传入一个初始化函数对象(initial function )作为新建进程执行入口;
继承multiprocessing.Process,并重写run函数;
方式1:
from multiprocessing import Process import os, time def pstart(name): # time.sleep(0.1) print("Process name: %s, pid: %s "%(name, os.getpid())) if __name__ == "__main__": subproc = Process(target=pstart, args=('subprocess',)) subproc.start() subproc.join() print("subprocess pid: %s"%subproc.pid) print("current process pid: %s" % os.getpid())
结果:
Process name: subprocess, pid: 4888 subprocess pid: 4888 current process pid: 9912
方式2:
from multiprocessing import Process import os, time class CustomProcess(Process): def __init__(self, p_name, target=None): # step 1: call base __init__ function() super(CustomProcess, self).__init__(name=p_name, target=target, args=(p_name,)) def run(self): # step 2: # time.sleep(0.1) print("Custom Process name: %s, pid: %s "%(self.name, os.getpid())) if __name__ == '__main__': p1 = CustomProcess("process_1") p1.start() p1.join() print("subprocess pid: %s"%p1.pid) print("current process pid: %s" % os.getpid())
这里可以思考一下,如果像多线程一样,存在一个全局的变量share_data,不同进程同时访问share_data会有问题吗?
由于每一个进程拥有独立的内存地址空间且互相隔离,因此不同进程看到的share_data是不同的、分别位于不同的地址空间,同时访问不会有问题。这里需要注意一下。
Subprocess模块
既然说道了多进程,那就顺便提一下另一种创建进程的方式。
python提供了Sunprocess模块可以在程序执行过程中,调用外部的程序。
如我们可以在python程序中打开记事本,打开cmd,或者在某个时间点关机:
>>> import subprocess >>> subprocess.Popen(['cmd']) <subprocess.Popen object at 0x0339F550> >>> subprocess.Popen(['notepad']) <subprocess.Popen object at 0x03262B70> >>> subprocess.Popen(['shutdown', '-p'])
或者使用ping测试一下网络连通性:
>>> res = subprocess.Popen(['ping', 'www.cnblogs.com'], stdout=subprocess.PIPE).communicate()[0] >>> print res 正在 Ping [101.37.113.127] 具有 32 字节的数据:
来自 101.37.113.127 的回复: 字节=32 时间=1ms TTL=91
来自 101.37.113.127 的回复: 字节=32 时间=1ms TTL=91
来自 101.37.113.127 的回复: 字节=32 时间=1ms TTL=91
来自 101.37.113.127 的回复: 字节=32 时间=1ms TTL=91
101.37.113.127 的 Ping 统计信息:
数据包: 已发送 = 4,已接收 = 4,丢失 = 0 (0% 丢失),
往返行程的估计时间(以毫秒为单位):
最短 = 1ms,最长 = 1ms,平均 = 1ms
先来看两个例子:
开启两个python线程分别做一亿次加一操作,和单独使用一个线程做一亿次加一操作:
def tstart(arg): var = 0 for i in xrange(100000000): var += 1 if __name__ == '__main__': t1 = threading.Thread(target=tstart, args=('This is thread 1',)) t2 = threading.Thread(target=tstart, args=('This is thread 2',)) start_time = time.time() t1.start() t2.start() t1.join() t2.join() print("Two thread cost time: %s" % (time.time() - start_time)) start_time = time.time() tstart("This is thread 0") print("Main thread cost time: %s" % (time.time() - start_time))
结果:
Two thread cost time: 20.6570000648 Main thread cost time: 2.52800011635
上面的例子如果只开启t1和t2两个线程中的一个,那么运行时间和主线程基本一致。这个后面会解释原因。
使用两个进程进行上面的操作: