python之subprocess
官网介绍:https://docs.python.org/3/library/subprocess.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 | Popen(): [root@oracle scripts] # cat sub_popen.py #!/usr/bin/python #coding=utf8 import subprocess child = subprocess.Popen([ 'ls' , '-l' ],shell = True ) print ( type (child)) print ( 'parent' ) [root@oracle scripts] # python sub_popen.py < class 'subprocess.Popen' > parent stu_subprocess.py sub_popen.py 如果将不添加shell,使用默认的: [root@oracle scripts] # cat sub_popen.py #!/usr/bin/python #coding=utf8 import subprocess child = subprocess.Popen([ 'ls' , '-l' ],shell = False ) shell参数默认为 False print ( type (child)) print ( 'parent' ) [root@oracle scripts] # python sub_popen.py < class 'subprocess.Popen' > parent total 8 - rw - r - - r - - 1 root root 256 Aug 21 15 : 26 stu_subprocess.py - rw - r - - r - - 1 root root 136 Aug 21 15 : 41 sub_popen.py Popen不会阻塞父进程运行,Popen启动新的进程与父进程并行执行,默认父进程不等待新进程结束。[root@oracle scripts] # cat test_subprocess.py #!/usr/bin/python #coding=utf8 def TestPopen(): import subprocess p = subprocess.Popen([ 'ls' , '-l' ],shell = True ) for i in range ( 5 ): print ( "other things" ) print (TestPopen()) [root@oracle scripts] # python test_subprocess.py other things other things other things other things other things None stu_subprocess.py sub_call.py sub_check_output.py sub_popen.py sub_run.py test_subprocess.py [root@oracle scripts] # cat test_subprocess1.py #!/usr/bin/python #coding=utf8 wait(): 阻塞父进程,等待子进程运行结束再继续运行父进程 def TestWait(): import subprocess import datetime print (datetime.datetime.now()) p = subprocess.Popen( 'sleep 10' ,shell = True ) p.wait() wait()阻塞了父进程的运行,等待子进程运行完成后才继续运行父进程 print (p.returncode) print (datetime.datetime.now()) TestWait() [root@oracle scripts] # python test_subprocess1.py 2017 - 08 - 21 16 : 49 : 15.061676 0 当子进程运行完成结束后,返回code为 0 2017 - 08 - 21 16 : 49 : 25.066657 poll():判断子进程是否结束 [root@oracle scripts] # cat test_subprocess2.py #!/usr/bin/python #coding=utf8 def TestWait(): import subprocess import datetime,time print (datetime.datetime.now()) p = subprocess.Popen( 'sleep 10' ,shell = True ) 子进程要睡眠 10 秒 t = 1 while (t < = 5 ): time.sleep( 1 ) p.poll() 执行判断子进程,这里花了 5 秒 print (p.returncode) t = t + 1 print (datetime.datetime.now()) TestWait() [root@oracle scripts] # python test_subprocess2.py 2017 - 08 - 21 16 : 56 : 33.672417 None None None None None 2017 - 08 - 21 16 : 56 : 38.684795 kill()或者terminate(): 杀掉子进程 [root@oracle scripts] # cat test_subprocess3.py #!/usr/bin/python #coding=utf8 def TestKillAndTerminate(): import subprocess import datetime,time print (datetime.datetime.now()) p = subprocess.Popen( 'sleep 10' ,shell = True ) t = 1 while (t < = 5 ): time.sleep( 1 ) t = t + 1 p.kill() print (datetime.datetime.now()) TestKillAndTerminate() [root@oracle scripts] # python test_subprocess3.py 2017 - 08 - 21 17 : 03 : 16.315531 2017 - 08 - 21 17 : 03 : 21.329266 可以看见子进程只运行了 5 秒 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | [root@oracle scripts] # cat sub_popen.py #!/usr/bin/python #coding=utf8 import subprocess child = subprocess.Popen([ 'ls' , '-l' ],shell = False ) child.wait() 阻塞父进程,直到子进程运行完成 print ( type (child)) print ( 'parent' ) [root@oracle scripts] # python sub_popen.py total 12 - rw - r - - r - - 1 root root 256 Aug 21 15 : 26 stu_subprocess.py - rw - r - - r - - 1 root root 135 Aug 21 15 : 47 sub_call.py - rw - r - - r - - 1 root root 149 Aug 21 15 : 47 sub_popen.py < class 'subprocess.Popen' > parent 可以看出先运行的子进程,最后才是父进程,等待子进程运行后,再运行父进程 除了wait()之外还有如下: child.poll() # 检查子进程状态 child.kill() # 终止子进程 child.send_signal() # 向子进程发送信号 child.terminate() # 终止子进程 子进程的PID存储在child.pid 子进程的标准输入、标准输出和标准错误如下属性分别表示: child.stdin child.stdout child.stderr |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | subprocess.PIPE实际上为文本流提供一个缓存区。child的stdout将文本输出到缓存区,然后打印出缓存区的内容: [root@oracle scripts] # cat sub_popen.py #!/usr/bin/python #coding=utf8 import subprocess child = subprocess.Popen([ 'ls' , '-l' ],shell = False ,stdout = subprocess.PIPE) print (child.stdout.read().decode( 'utf-8' )) 打印缓存区内容,由于是bytes格式,所以转码 print ( 'parent' ) [root@oracle scripts] # python sub_popen.py total 16 - rw - r - - r - - 1 root root 256 Aug 21 15 : 26 stu_subprocess.py - rw - r - - r - - 1 root root 148 Aug 21 15 : 53 sub_call.py - rw - r - - r - - 1 root root 183 Aug 21 16 : 07 sub_popen.py - rw - r - - r - - 1 root root 147 Aug 21 15 : 56 sub_run.py parent |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | communicate() Popen.communicate( input = None ):与子进程进行交互。向stdin发送数据,或从stdout和stderr中读取数据。可选参数 input 指定发送到子进程的参数。Communicate()返回一个元组:(stdoutdata, stderrdata)。注意:如果希望通过进程的stdin向其发送数据,在创建Popen对象的时候,参数stdin必须被设置为PIPE。同样,如果希望从stdout和stderr获取数据,必须将stdout和stderr设置为PIPE。 [root@oracle scripts] # cat sub_popen.py #!/usr/bin/python #coding=utf8 import subprocess child = subprocess.Popen([ 'ls' , '-l' ],shell = False ,stdout = subprocess.PIPE) #print(child.stdout.read().decode('utf-8')) print (child.communicate()) 返回的是标准输出,标准错误输出的 tuple print ( 'parent' ) [root@oracle scripts] # python sub_popen.py (b 'total 16\n-rw-r--r-- 1 root root 256 Aug 21 15:26 stu_subprocess.py\n-rw-r--r-- 1 root root 148 Aug 21 15:53 sub_call.py\n-rw-r--r-- 1 root root 211 Aug 21 16:11 sub_popen.py\n-rw-r--r-- 1 root root 147 Aug 21 15:56 sub_run.py\n' , None ) NONE就是标准错误输出结果 parent 可以看见先输出的子进程内容,然后才是父进程,communicate()是Popen对象的一个方法,该方法会阻塞父进程,直到子进程完成 [root@oracle scripts] # cat sub_popen.py #!/usr/bin/python #coding=utf8 import subprocess child1 = subprocess.Popen([ 'cat' , '/etc/passwd' ],shell = False ,stdout = subprocess.PIPE) child2 = subprocess.Popen([ 'grep' , '0:0' ],stdin = child1.stdout, stdout = subprocess.PIPE) # subprocess.PIPE实际上为文本流提供一个缓存区。child1的stdout将文本输出到缓存区,随后child2的stdin从该PIPE中将文本读取走。child2的输出文本也被存放在PIPE中,直到communicate()方法从PIPE中读取出PIPE中的文本。 out,err = child2.communicate() 因为communicate()返回的是一个元祖 print (out) 纸打印出标准输出内容 print ( 'parent' ) [root@oracle scripts] # python sub_popen.py b 'root:x:0:0:root:/root:/bin/bash\n' parent child1.stdout - - >subprocess.PIPE child2.stdin< - - subprocess.PIPE child2.stdout - - >subprocess.PIPE 利用communicate()实现交互: [root@oracle scripts] # cat stu_subprocess.py #!/usr/bin/python #coding=utf8 import subprocess child1 = subprocess.Popen([ 'python' ],stdin = subprocess.PIPE,stdout = subprocess.PIPE,stderr = subprocess.PIPE) out,err = child1.communicate(b 'print("hello")\nexit()' ) 继续给子进程输入信息 # 启动一个子进程,然后控制其输入和输出 print (out.decode( 'utf-8' )) print ( 'parent' ) [root@oracle scripts] # python stu_subprocess.py hello parent[root@oracle scripts] # cat sub_popen2.py #!/usr/bin/python #coding=utf8 import subprocess obj = subprocess.Popen([ "python" ], stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr = subprocess.PIPE) obj.stdin.write(b 'print("hello")\n' ) stdin.write和communicate两者交换使用 obj.stdin.write(b 'print("world")' ) out,err = obj.communicate() print (out) [root@oracle scripts] # python sub_popen2.py b 'hello\nworld\n' |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | call(): subprocess.call() 父进程等待子进程完成 返回退出信息(returncode,相当于Linux exit code) [root@oracle scripts] # cat sub_call.py #!/usr/bin/python #coding=utf8 import subprocess child = subprocess.call([ 'ls' , '-l' ],shell = False ) print ( type (child)) print ( 'parent' ) [root@oracle scripts] # python sub_call.py total 12 - rw - r - - r - - 1 root root 256 Aug 21 15 : 26 stu_subprocess.py - rw - r - - r - - 1 root root 135 Aug 21 15 : 45 sub_call.py - rw - r - - r - - 1 root root 136 Aug 21 15 : 41 sub_popen.py < class 'int' > call函数返回的是 int parent 调用call函数可以明显看出子进程阻塞了主进程的运行,先运行子进程,最后才是主进程 [root@oracle scripts] # cat sub_call.py #!/usr/bin/python #coding=utf8 import subprocess child = subprocess.call([ 'ls' , '-l' ],shell = False ) print ( type (child)) print (child) - - - - - >returncode print ( 'parent' ) [root@oracle scripts] # python sub_call.py total 12 - rw - r - - r - - 1 root root 256 Aug 21 15 : 26 stu_subprocess.py - rw - r - - r - - 1 root root 148 Aug 21 15 : 53 sub_call.py - rw - r - - r - - 1 root root 149 Aug 21 15 : 47 sub_popen.py < class 'int' > 0 parent subprocess.call( * popenargs, * * kwargs):运行命令。该函数将一直等待到子进程运行结束,并返回进程的returncode。如果子进程不需要进行交互,就可以使用该函数来创建。 call函数返回的是returncode,也就是 int 类型 根据shell类型不同,可以更改传入call函数的args类型: [root@oracle scripts] # cat sub_call.py #!/usr/bin/python #coding=utf8 import subprocess child = subprocess.call( "ls -l" ,shell = True ) print ( type (child)) print (child) print ( 'parent' ) shell = True 参数会让subprocess.call接受字符串类型的变量作为命令,并调用shell去执行这个字符串,当shell = False 是,subprocess.call只接受数组变量作为命令,并将数组的第一个元素作为命令,剩下的全部作为该命令的参数。 [root@oracle scripts] # python sub_call.py total 40 - rw - r - - r - - 1 root root 256 Aug 21 15 : 26 stu_subprocess.py - rw - r - - r - - 1 root root 143 Aug 21 17 : 22 sub_call.py - rw - r - - r - - 1 root root 143 Aug 21 16 : 33 sub_check_output.py - rw - r - - r - - 1 root root 162 Aug 21 17 : 17 sub_getoutput.py - rw - r - - r - - 1 root root 279 Aug 21 16 : 17 sub_popen.py - rw - r - - r - - 1 root root 148 Aug 21 16 : 29 sub_run.py - rw - r - - r - - 1 root root 257 Aug 21 16 : 53 test_subprocess1.py - rw - r - - r - - 1 root root 340 Aug 21 16 : 52 test_subprocess2.py - rw - r - - r - - 1 root root 332 Aug 21 17 : 03 test_subprocess3.py - rw - r - - r - - 1 root root 183 Aug 21 16 : 44 test_subprocess.py < class 'int' > 0 parent 所以当shell默认为 False 时,args传入的值必须是列表,而不能是 str from subprocess import call import shlex cmd = "cat test.txt; rm test.txt" call(cmd, shell = True ) shell介绍: https: / / zhidao.baidu.com / question / 651286079254739125.html |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | 3.5 新增的run(): class subprocess.CompletedProcess The return value from run(), representing a process that has finished. [root@oracle scripts] # cat sub_run.py #!/usr/bin/python #coding=utf8 import subprocess child = subprocess.run([ 'ls' , '-l' ],shell = False ) print ( type (child)) print (child) print ( 'parent' ) [root@oracle scripts] # python sub_run.py total 16 - rw - r - - r - - 1 root root 256 Aug 21 15 : 26 stu_subprocess.py - rw - r - - r - - 1 root root 148 Aug 21 15 : 53 sub_call.py - rw - r - - r - - 1 root root 149 Aug 21 15 : 47 sub_popen.py - rw - r - - r - - 1 root root 147 Aug 21 15 : 56 sub_run.py < class 'subprocess.CompletedProcess' > CompletedProcess(args = [ 'ls' , '-l' ], returncode = 0 ) parent |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | check_output(): [root@oracle scripts] # cat sub_check_output.py #!/usr/bin/python #coding=utf8 import subprocess child = subprocess.check_output([ 'ls' , '-l' ],shell = False ) print ( type (child)) print (child) print ( 'parent' ) [root@oracle scripts] # python sub_check_output.py < class 'bytes' > b 'total 20\n-rw-r--r-- 1 root root 256 Aug 21 15:26 stu_subprocess.py\n-rw-r--r-- 1 root root 148 Aug 21 15:53 sub_call.py\n-rw-r--r-- 1 root root 156 Aug 21 16:26 sub_check_output.py\n-rw-r--r-- 1 root root 279 Aug 21 16:17 sub_popen.py\n-rw-r--r-- 1 root root 147 Aug 21 15:56 sub_run.py\n' parent [root@oracle scripts] # cat sub_check_output.py #!/usr/bin/python #coding=utf8 import subprocess child = subprocess.check_output([ 'ls' , '-l' ],shell = False ) print ( type (child)) print ( 'parent' ) [root@oracle scripts] # python sub_check_output.py < class 'bytes' > parent 并没有打印出子进程运行后的内容 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | subprocess.getoutput(cmd),返回的是一个字符串 Return output (stdout and stderr) of executing cmd in a shell. [root@oracle scripts] # python sub_getoutput.py < class 'str' > stu_subprocess.py sub_call.py sub_check_output.py sub_getoutput.py sub_popen.py sub_run.py test_subprocess1.py test_subprocess2.py test_subprocess3.py test_subprocess.py [root@oracle scripts] # cat sub_getoutput.py #!/usr/bin/python #coding=utf8 import subprocess def TestGetOutput(): outp = subprocess.getoutput([ "ls" , "-l" ]) 列表 print ( type (outp)) print (outp) TestGetOutput() [root@oracle scripts] # cat sub_getoutput.py #!/usr/bin/python #coding=utf8 import subprocess def TestGetOutput(): outp = subprocess.getoutput( "ls -l" ) 字符串 print ( type (outp)) print (outp) TestGetOutput() [root@oracle scripts] # python sub_getoutput.py < class 'str' > total 40 - rw - r - - r - - 1 root root 256 Aug 21 15 : 26 stu_subprocess.py - rw - r - - r - - 1 root root 148 Aug 21 15 : 53 sub_call.py - rw - r - - r - - 1 root root 143 Aug 21 16 : 33 sub_check_output.py - rw - r - - r - - 1 root root 162 Aug 21 17 : 17 sub_getoutput.py - rw - r - - r - - 1 root root 279 Aug 21 16 : 17 sub_popen.py - rw - r - - r - - 1 root root 148 Aug 21 16 : 29 sub_run.py - rw - r - - r - - 1 root root 257 Aug 21 16 : 53 test_subprocess1.py - rw - r - - r - - 1 root root 340 Aug 21 16 : 52 test_subprocess2.py - rw - r - - r - - 1 root root 332 Aug 21 17 : 03 test_subprocess3.py - rw - r - - r - - 1 root root 183 Aug 21 16 : 44 test_subprocess.py |
1 2 3 | #接收字符串格式命令,返回元组形式,第1个元素是执行状态,第2个是命令结果 >>> subprocess.getstatusoutput( 'ls -l' ) ( 0 , 'total 40\n-rw-r--r-- 1 root root 256 Aug 21 15:26 stu_subprocess.py\n-rw-r--r-- 1 root root 143 Aug 21 17:22 sub_call.py\n-rw-r--r-- 1 root root 143 Aug 21 16:33 sub_check_output.py\n-rw-r--r-- 1 root root 162 Aug 21 17:17 sub_getoutput.py\n-rw-r--r-- 1 root root 279 Aug 21 16:17 sub_popen.py\n-rw-r--r-- 1 root root 148 Aug 21 16:29 sub_run.py\n-rw-r--r-- 1 root root 257 Aug 21 16:53 test_subprocess1.py\n-rw-r--r-- 1 root root 340 Aug 21 16:52 test_subprocess2.py\n-rw-r--r-- 1 root root 332 Aug 21 17:03 test_subprocess3.py\n-rw-r--r-- 1 root root 183 Aug 21 16:44 test_subprocess.py' ) |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!