Python自动化开发学习5-2-subprocess模块

简介:

之前的课还有一个模块没有讲

subprocess模块

运行系统命令,管理子进程。是对这些命令的替换 os.system 和 os.spawn* 。所以尽量用subprocess。

run() 运行命令

python3.5之后有了subprocess.run(),这个是官方推荐的运行系统命令的方法。用nslookup举例:

1
2
3
4
5
import  subprocess
subprocess.run([ "nslookup" , "www.baidu.com" , "114.114.114.114" ])   # 命令和参数之间必须用列表分开
subprocess.run([ "nslookup" , "www.baidu.com 114.114.114.114" ])   # 参数写在一起貌似没问题
subprocess.run([ "nslookup" , "-qt=cname" , "www.baidu.com" , "114.114.114.114" ])   # 不过最好还是分开写
subprocess.run( "nslookup -qt=cname www.baidu.com 114.114.114.114" ,shell = True )   # 也可以全部混在一起写,但是shell参数得设成True

上面的shell参数,主要是用在涉及到命令行中有多个命令的情况。因为默认只会解析列表的第一个元素作为命令,后面都是命令的参数。具体情况,比如Linux中的管道命令:ls -l | grep test

上面只有屏幕输出,也可以取得返回值,包括命令的参数和执行的结果:

1
2
3
4
import  subprocess
res  =  subprocess.run([ "nslookup" , "www.baidu.com" , "114.114.114.114" ])
print (res)
print (res.returncode)   # 取得命令的结果

相关命令和参数,可以help(subprocess.Popen) 查看,因为底层其实是通过subprocess.Popen来实现的。

run很方便,但是如果想要获取屏幕上的输出保存,那就需要用底层的Popen来实现了。用stdout来指定程序的标准输出。

1
2
3
4
5
6
7
8
9
import  subprocess
res  =  subprocess.Popen(
     [ "nslookup" , "www.baidu.com" , "114.114.114.114" ],
     stdout = subprocess.PIPE)   # 将标准输出指向PIPE
res_read  =  res.stdout.read()   # 和文件一样,read完就没了,所以先read到变量里
print (res_read)   # 这里读到的内容是二进制
print ((res_read).decode( "gbk" ))   # 将二进制转码,这里是操作系统的编码格式,我用的是windows,所以是gbk
print (res.poll())   # 最后2个属性返回的都是命令执行的结果,即returncode。正常执行应该都是返回0
print (res.wait())

poll() 和 wait()  的区别

poll():检查是否结束,设置并返回returncode属性。

wait():等待结束,设置并返回returncode属性。

所以命令运行时间长的时候,wait()会一直等下去,poll()会直接返回,如果还没有结束,返回None

1
2
3
4
5
6
7
8
9
import  subprocess,time
res  =  subprocess.Popen(
     [ "nslookup" , "www.baidu.com" , "1.1.1.1" ],
     stdout = subprocess.PIPE)   # 这里用一个部存在的地址,这样命令要等待很久
#print("wait:",res.wait())  # 去掉注释,看看wait的效果
while  res.poll() = = None :
     print ( "poll:" ,res.poll())
     time.sleep( 1 )
print ( "end poll" ,res.poll())

使用poll,在运行命令等待结果的同时,并不会中断python的运行,可以随时用poll检查命令是否执行完成。

terminate()  终止进程,kill

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import  subprocess,time
res  =  subprocess.Popen(
     [ "nslookup" , "www.baidu.com" , "1.1.1.1" ],
     stdout = subprocess.PIPE)   # 这里用一个部存在的地址,这样命令要等待很久
=  3
while  n> 0 :
     print ( "poll:" ,res.poll())
     time.sleep( 1 )
     - =  1
else :
     if  res.poll()  = =  None :
         print ( "终止进程" )
         res.terminate()   # 如果还没执行完,就终止进程
print (res.stdout.read())   # 这里是空的,因为并没有结果

如果一段时间内没有执行完成,就终止这个进程。把最后的参数改成一个有响应的IP,不会超时就可以顺利执行完。

communictae(input=None)

和子进程交互:发送数据到stdin,并从stdout和stderr读数据,直到收到EOF。等待子进程结束。可选的input如有有的话,要为bytes类型。
此函数返回一个元组: (stdoutdata , stderrdata ) 。

主要用于需要交互的命令(nslookup telnet这种):

1
2
3
4
5
6
7
8
9
10
11
12
import  subprocess
=  subprocess.Popen( 'nslookup' ,shell = True ,
                      stdin = subprocess.PIPE,
                      stdout = subprocess.PIPE,
                      stderr = subprocess.PIPE)   # 输入、输出、错误都得进管道
p.stdin.write(b 'server 114.114.114.114 \n' )   # 只接收bytes,记得要打上回车符
p.stdin.write(b 'www.baidu.com \n' )
p.stdin.write(b 'exit \n' )
res  =  p.communicate()   # 上面的write只是写入到内存,这句才是把之前写入的所有的内容传给进程来执行
#res = p.communicate(b"exit \n")  # input参数没啥用,这个效果测试下来等于上面2句
print (res[ 0 ].decode( "gbk" ))   # 第一个元素是标准输出
print (res[ 1 ].decode( "gbk" ))   # 第二个是标准错误。"非权威应答:"作为错误信息返回了

可用参数:

  • args:shell命令,可以是字符串或者序列类型(如:list,元组)

  • bufsize:指定缓冲。0 无缓冲,1 行缓冲,其他 缓冲区大小,负值 系统缓冲

  • stdin, stdout, stderr:分别表示程序的标准输入、输出、错误句柄

  • preexec_fn:只在Unix平台下有效,用于指定一个可执行对象(callable object),它将在子进程运行之前被调用

  • close_sfs:在windows平台下,如果close_fds被设置为True,则新创建的子进程将不会继承父进程的输入、输出、错误管道。
    所以不能将close_fds设置为True同时重定向子进程的标准输入、输出与错误(stdin, stdout, stderr)。

  • shell:默认False,如果为True,指定的命令会在shell里解释执行。

  • cwd:用于设置子进程的当前目录

  • env:用于指定子进程的环境变量。如果env = None,子进程的环境变量将从父进程中继承。

  • universal_newlines:不同系统的换行符不同,True -> 同意使用 \n

  • startupinfo与createionflags只在windows下有效
    将被传递给底层的CreateProcess()函数,用于设置子进程的一些属性,如:主窗口的外观,进程的优先级等等

最后还有一个例子,具体可能没什么用。要自动输入密码的时候会遇到,但是其实linux里也有单行命令,通过stdin来解决传入密码的问题了。

1
2
3
4
5
6
7
8
9
10
11
import  subprocess
# Windows要用echo,必须要加上shell=True才行
echo  =  subprocess.Popen([ "echo" , "server" ],
                         shell = True ,
                         stdout = subprocess.PIPE)
# 把上面echo的输出,作为这里命令执行后的输入
cmd  =  subprocess.Popen([ "nslookup" ],
                        stdin = echo.stdout,
                        stdout = subprocess.PIPE)
end_of_pipe  =  cmd.stdout   # 这里执行cmd,然后cmd中会调用echo
print (end_of_pipe.read())   # 转码就略过了

上课讲过之后,暂时想不到还有哪里能用的到,可以忘记它。










本文转自骑士救兵51CTO博客,原文链接:http://blog.51cto.com/steed/2043482,如需转载请自行联系原作者

相关文章
|
1天前
|
运维 Shell Python
Shell和Python学习教程总结
Shell和Python学习教程总结
|
2天前
|
Python
Python从入门到精通:深入学习面向对象编程——2.1.2继承、封装和多态的概念
Python从入门到精通:深入学习面向对象编程——2.1.2继承、封装和多态的概念
|
2天前
|
开发框架 前端开发 数据库
Python从入门到精通:3.3.2 深入学习Python库和框架:Web开发框架的探索与实践
Python从入门到精通:3.3.2 深入学习Python库和框架:Web开发框架的探索与实践
|
2天前
|
数据采集 数据可视化 数据处理
Python从入门到精通的文章3.3.1 深入学习Python库和框架:数据处理与可视化的利器
Python从入门到精通的文章3.3.1 深入学习Python库和框架:数据处理与可视化的利器
|
2天前
|
存储 网络协议 关系型数据库
Python从入门到精通:2.3.2数据库操作与网络编程——学习socket编程,实现简单的TCP/UDP通信
Python从入门到精通:2.3.2数据库操作与网络编程——学习socket编程,实现简单的TCP/UDP通信
|
2天前
|
测试技术 API 网络架构
Python的api自动化测试 编写测试用例
【4月更文挑战第18天】使用Python进行API自动化测试,可以结合`requests`库发送HTTP请求和`unittest`(或`pytest`)编写测试用例。以下示例: 1. 安装必要库:`pip install requests unittest` 2. 创建`test_api.py`,导入库,定义基础URL。 3. 创建继承自`unittest.TestCase`的测试类,包含`setUp`和`tearDown`方法。 4. 编写测试用例,如`test_get_users`,检查响应状态码和内容。 5. 运行测试:`python -m unittest test_api.py`
12 2
|
2天前
|
JSON 测试技术 API
Python的Api自动化测试使用HTTP客户端库发送请求
【4月更文挑战第18天】在Python中进行HTTP请求和API自动化测试有多个库可选:1) `requests`是最流行的选择,支持多种请求方法和内置JSON解析;2) `http.client`是标准库的一部分,适合需要低级别控制的用户;3) `urllib`提供URL操作,适用于复杂请求;4) `httpx`拥有类似`requests`的API,提供现代特性和异步支持。根据具体需求选择,如多数情况`requests`已足够。
9 3
|
3天前
|
人工智能 Python
【Python实用技能】建议收藏:自动化实现网页内容转PDF并保存的方法探索(含代码,亲测可用)
【Python实用技能】建议收藏:自动化实现网页内容转PDF并保存的方法探索(含代码,亲测可用)
21 0
|
3天前
|
开发者 Python
Python的os模块详解
Python的os模块详解
15 0
|
3天前
|
测试技术 持续交付 API
Python的UI自动化测试
【4月更文挑战第17天】Python UI自动化测试涉及Selenium(Web)、Appium(移动应用)和PyQt(桌面应用)等框架。基本步骤包括确定测试目标、选择合适框架、安装配置、编写测试脚本、运行调试以及集成到CI/CD流程。注意自动化测试不能完全取代人工测试,应根据需求平衡使用。
8 1

热门文章

最新文章