赞
踩
线程是CPU使用的基本单元,由主线程来创建,并使用这个进程的资源。python中thread模块提供支持,通过以下两种方法创建线程:
这里我们就用这个函数创建一个线程,简单模拟打印平方,这个函数原型我们首先熟悉一下,尤其是各个参数
Thread(group=None, target=None, Name=None, args=(), kwargs={}, *, daemon = None)
# 其中target参数就是运行的函数,args是传入函数的参数元组。
运行效果:(并行效果哟!)
import threading
def thrfun(x, y):
for i in range(x, y):
print(str(i * i) + ';')
ta = threading.Thread(target=thrfun, args=(1, 6))
tb = threading.Thread(target=thrfun, args=(16, 21))
tc = threading.Thread(target=thrfun, args=(11,15))
ta.start()
tb.start()
tc.start()
博主用pycharm是同步执行,但是代码本身含义是并行。因此大家如果使用pycharm同步的话,可以用ipython试试。
这个创建类来继承就行了,了解面向对象的同学应该明白,肯定有init的方法,我们把要执行的函数写到run函数里,因为它继承可以重载。我们还是仍以求平方为例子
实验效果:
实验代码:
import threading class myThread(threading.Thread): def __init__(self,mynum): super().__init__() self.mynum = mynum def run(self): for i in range(self.mynum,self.mynum+5): print(str(i*i)+';') ma = myThread(1) mb = myThread(16) ma.start() mb.start()
上面的例子我们只是用thread里的init和run方法,还有几个重要的方法和属性一起熟悉一下:
方法:
属性:
# join()方法的作用是当某个线程或函数执行时需等另一个线程
# --完成后才能继续,则应调用另一个线程的join()方法
# 其中可选参数timeout用于指定线程运行的最长时间
# isAlive()方法用于查看线程是否运行
# 属性
# name属性是线程设置的线程名
# daemon属性用来设置线程是否随主线程退出而退出,一般来说,其属性值为True不会随主线程退出而退出
下面就以两个例子演示join和daemon的使用
实验效果:
实验代码:
import threading import time def thrfun(x, y, thr=None): if thr: thr.join() else: time.sleep(2) for i in range(x, y): print(str(i * i) + ';') ta = threading.Thread(target=thrfun, args=(1, 6)) tb = threading.Thread(target=thrfun, args=(16, 21,ta)) ta.start() tb.start()
这里的join函数本传入了ta,也就是tb线程应等待ta结束后运行。
实验效果:
实验代码:
import threading import time class myThread(threading.Thread): def __init__(self,mynum): super().__init__() self.mynum = mynum def run(self): time.sleep(1) for i in range(self.mynum, self.mynum + 5): print(str(i * i) + ';') def main(): print('start...') ma = myThread(1) mb = myThread(16) ma.daemon =True mb.daemon = True ma.start() mb.start() print('end...') if __name__ == '__main__': main()
将打印平方的工作,都交到后台去了,这里不做执行
线程的隔离性就不需要彼此修改,因此产生锁的概念。python中threading模块中的对象Lock和RLock进行简单的同步,对于同一个时刻只允许一个线程操作的数据对象,可以进行加锁和解锁进行隔离。过程原型如下
lock = threading.RLock() # 创建lock对象
lock.acquire() # 开始锁定
pass # pass就是指我们要执行的语句和操作
lock.release() # 释放锁
线程间的通信我们用Event对象,Event实例管理着一个内部标志,通过set()方法会将它设置为True,使用clear()方法会将它重置为False,wait([timeout])方法会使当前线程阻塞标志为True.
下面我们用两个例子进行简单模拟,一个是打印数据每次加30,第二个是两个进程通信
实验效果:
实验代码:
import threading import time class myThread(threading.Thread): def run(self): global x lock.acquire() for i in range(3): x += 10 time.sleep(1) print(x) lock.release() x = 0 lock = threading.RLock() def main(): thrs = [] for item in range(5): thrs.append(myThread()) for item in thrs: item.start() if __name__ == '__main__': main()
实验效果
实验代码:
import threading import time class myThreada(threading.Thread): def run(self): evt.wait() print(self.name,':Good morning!') evt.clear() time.sleep(1) evt.set() time.sleep(1) evt.wait() print(self.name,":I'm fine,thank you.") class myThreadb(threading.Thread): def run(self): print(self.name,':Good morning!') evt.set() time.sleep(1) evt.wait() print(self.name,":How are you?") evt.clear() time.sleep(1) evt.set() evt = threading.Event() def main(): John = myThreada() John.name = 'John' Smith = myThreadb() Smith.name = 'Smith' John.start() Smith.start() if __name__ == '__main__': main()
使用python的多进程模块可以将工作分配给不受锁定限制的单独子进程。python3对多进程支持的是multiprocessing模块和subprocess模块。使用multiprocessing模块创建和使用多线程,基本上和threading模块的使用方法一致。创建进程使用multiprocessing.Process对象来完成。
下面我们用subprocess创建模块,它用来创建新进程,获取进程的输入、输出以及错误信息。它提供了更高级的接口,可以替换os.system、os.spawn*、popen等,subprocess模块的基本函数如下:
call(args,*,stdin = None,stdout=None,stderr = None,shell=False,timeout=None)
# 创建新进程运行程序,输入输出绑定到父进程,返回新进程的退出码
check_call(args,*,stdin = None,stdout=None,stderr = None,shell=False,timeout=None)
# 创建新进程运行程序,输入和输出绑定到父进程,退出码为0正常返回
# 否则,返回CalledProcessError
getstatusoutput(cmd)
# 创建新进程运行程序,元组形式返回新进程退出码和输出
getoutput(cmd)
# 创建新进程运行程序,返回新进程输出(字符串)
call(args,*,input=None,stdin = None,stdout=None,stderr = None,shell=False,
universal_newlines=False,timeout=None)
# 创建新进程运行程序,返回新进程的输出(bytesarray)
下面我们用一个例子演示如何操作,
实验准备,新建protest.py,内容为:
print('hello world!')
实验效果:
实验代码:
import subprocess
print('call() test:',subprocess.call(['python','protest.py']))
print('')
print('check_call() test:',subprocess.check_call(['python','protest.py']))
print('getstatusoutput() test:',subprocess.getstatusoutput(['python','protest.py']))
print('')
print('getoutput() test:',subprocess.getoutput(['python','protest.py']))
print('')
print('check_output() test:', subprocess.check_output(['python','protest.py']))
Popen也可以创建新进程,它是一个类,因此初始化参数如下:
class Popen(args, bufsize = -1,executable = None, stdin = None, stdout = None,stderr = None,
preexec_fn = None,close_fds = True,shell = False,cwd = None,env = None,
universal_newlines = False,startupinfo = None, creationflags = 0,
restore_signals = True,start_new_session = False,pass_fds =())
因为大部分参数都跟上面类似,我们用到啥就直接等于啥。以下常用方法
其中常用属性有:
下面用两个例子演示popen创建子进程和communicate函数的效果
实验准备:创建protest.py文件,内容为:
print('hello world!')
print(a)
实验效果:因a没有赋值,所以会报错
实验代码:
import subprocess
prcs = subprocess.Popen(['python','protest.py'],stdout=subprocess.PIPE,
stdin=subprocess.PIPE,
stderr=subprocess.PIPE,
universal_newlines=True,
shell=True)
prcs.communicate('These strings are from stdin.')
print('subprocess pid:',prcs.pid)
print('\nSTDOUT:')
print(str(prcs.communicate()[0]))
print('STDERR:')
print(prcs.communicate()[1])
实验准备,创建protest1.py内容为:
a = input()
a = a.split(' ')
a[0] = str(int(a[0])+1)
print(' '.join(a))
实验效果
实验代码:
import subprocess processes = [] psum = 5 for i in range(psum): processes.append(subprocess.Popen(['python','protest1.py'],stdout=subprocess.PIPE, stdin=subprocess.PIPE, universal_newlines=True, shell = True)) processes[0].communicate('0 bouquet of flowers!') for before,after in zip(processes[:psum],processes[1:]): after.communicate(before.communicate()[0]) print('\nSum of Process :%d'%psum) print() for item in processes: print(item.communicate()[0])
通过线程与进程的学习,能自己创建进程与线程,在后面的学习中,可以对这些不断强化,进而完成掌握的功底!程序员是码出来的,加油!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。