【Python基础】Python中执行系统命令
常见四种方法
- os.system()
- os.popen()
- subprocess.call()
- subprocess.Popen()
os.system()
os.system(command)
调用os.system()函数后,程序会暂停执行,直到该命令执行完毕才会继续执行Python程序。
- 优点:
简单易用,可以快速执行简单的系统命令。 - 缺点:
无法获取系统命令的输出结果,也无法对命令执行过程进行控制。
os.popen()
os.popen(command [, mode [, bufsize]])
- command是需要执行的系统命令
- mode是读取命令输出的模式(默认为“r”)
- bufsize是读取缓冲区的大小(默认为-1)
调用os.popen()函数后,可以通过read()、readline()、readlines()等方法来读取命令的输出结果。
- 优点:
可以获取系统命令的输出结果 - 缺点:
无法对命令执行过程进行控制,也无法获取命令的返回值。
subprocess.call()
subprocess.call(args, *, stdin=None, stdout=None, stderr=None, shell=False)
- args是需要执行的系统命令和参数,以列表的形式传入
- stdin、stdout、stderr是分别指定命令的标准输入、标准输出和标准错误输出
- shell为True时,可以执行shell命令。
调用subprocess.call()函数后,程序会暂停执行,直到该命令执行完毕才会继续执行Python程序。函数的返回值为命令的返回值。
- 优点:
可以获取系统命令的返回值 - 缺点:
无法对命令执行过程进行控制,也无法获取命令的输出结果。
subprocess.Popen()
subprocess.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)
- args:要执行的命令及其参数,可以是字符串或序列,如果是序列,第一个元素通常是要执行的命令,后续元素是命令参数。
- bufsize:缓冲区大小,对于标准 IO 通道,这个值默认为 -1,表示使用系统默认值。
- executable:指定要使用的可执行文件,通常是 shell 程序。
- stdin, stdout,stderr:表示标准输入、输出和错误的管道,可以是文件描述符或者一个文件对象。
- preexec_fn:在子进程启动前执行的函数。
- close_fds:是否关闭所有父进程打开的文件描述符,默认为 True。
- shell:如果设置为 True,则将 args 参数作为一个字符串传递给 shell 进行解析,默认为 False。
- cwd:在执行命令之前改变当前工作目录。
- env:指定环境变量,可以是一个字典或者 None。
- universal_newlines:如果设置为 True,则将输入和输出转换为文本模式,默认为 False 也就是二进制流模式。
- startupinfo:指定一些 Windows 特定的属性,例如窗口大小、标准输入模式等等。
- creationflags:可以用来控制子进程的创建方式,例如是否使用CREATE_NEW_CONSOLE 来创建控制台窗口。
调用subprocess.Popen()函数后,程序可以先执行Python程序的其他部分,而不需要等待命令执行完毕。
可以通过wait()方法等待命令执行完毕,获取命令的返回值;也可以通过communicate()方法获取命令的输出结果。
- 优点:
可以获取系统命令的输出结果和返回值,同时也可以对命令执行过程进行控制 - 缺点:
比其他三种方法复杂一些
subprocess.Popen()工具使用及封装
import logging
import os
import subprocess
import sys
import time
from tools.unit import file_path
class SubProcess:
@classmethod
def shell_subprocess(cls, cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE):
return subprocess.Popen(cmd, shell=shell, stdout=stdout, stderr=stderr)
@classmethod
def stop_server(cls, port):
mac_cmd = f"lsof -i tcp:{port}"
win_cmd = f"netstat -ano | findstr {port}"
# 判断操作系统
os_platform = sys.platform
# print('操作系统:', os_platform)
# #windows 系统
if os_platform == "win32":
win_p = cls.shell_subprocess(win_cmd)
for line in win_p.stdout.readlines():
if line:
line = line.decode('utf8')
if "LISTENING" in line:
win_pid = line.split("LISTENING")[1].strip()
os.system(f"taskkill -f -pid {win_pid}")
else:
# unix系统
p = cls.shell_subprocess((mac_cmd))
for line in p.stdout.readlines():
line = line.decode('utf8')
if "node" in line:
stdoutline = line.split(" ")
# print(stdoutline)
pid = stdoutline[4]
os.system(f"kill {pid}")
logging.info(f"服务{port}端口已关闭")
@classmethod
def start_server(cls, port, cmd, log_path):
cls.stop_server(port)
if not os.path.exists(log_path):
os.mkdir(log_path)
log_name = str(port) + '-' + time.strftime('%Y_%m_%d') + ".log"
appium_logs_dirName = os.path.join(log_path, log_name)
cls.shell_subprocess(cmd, shell=True, stdout=open(appium_logs_dirName, mode='a', encoding="utf8"),
stderr=subprocess.PIPE)
logging.info(f"服务{port}端口已开启")
class AdbSever(SubProcess):
@classmethod
def run_command(cls, cmd):
cls.shell_subprocess(cmd)
@classmethod
def get_command(cls, cmd):
p = cls.shell_subprocess(cmd, shell=False)
value = p.stdout.readline()
return value.decode("utf-8").replace('\r\n', '')
@classmethod
def get_devices_list(cls):
cmd = "adb devices"
p = cls.shell_subprocess(cmd, shell=False)
lists = p.stdout.readlines()
devicesList = []
for item in lists:
itemStr = str(item, encoding="utf-8")
if (itemStr.strip() == ""):
continue
elif (itemStr.startswith("List of")):
continue
elif (itemStr.find("daemon") > -1):
continue
else:
infos = itemStr.split("\t")
devicesList.append({
"deviceId": infos[0],
"type": infos[1].replace('\r\n', '')
})
return devicesList
class AppiumServer(SubProcess):
@classmethod
def stop_appium(cls, port):
cls.stop_server(port)
logging.info(f"appium服务{port}端口已关闭")
@classmethod
def start_appium(cls, port):
"""
启动appium 服务
:param port: 服务的端口号
:return:
"""
cls.stop_appium(port)
cmd = f"appium -p {port}"
appium_logs = file_path("logs", "appium_logs")
cls.start_server(port, cmd, appium_logs)
logging.info(f"appium服务{port}端口已开启")
class AllureServer(SubProcess):
@classmethod
def create_html(cls, path):
# allure生成报表,并启动程序
# logging.info(f"allure数据路径:{path}_result/")
# logging.info(f"allure存入路径:{path}_html")
return subprocess.call(f'allure generate {path}_result/ -o {path}_html --clean', shell=True)
@classmethod
def stop_allure(cls, port):
cls.stop_server(port)
logging.info(f"allure服务{port}端口已关闭")
@classmethod
def start_allure(cls, port, path):
"""
启动Allure 服务
:param port: 服务的端口号
:return:
"""
cls.stop_allure(port)
cmd = f"allure open -h 127.0.0.1 -p {port} {path}"
allure_logs = file_path("logs", "allure_logs")
# logging.info(f"allure服务启动路径:{allure_logs}")
cls.start_server(port, cmd, allure_logs)
logging.info(f"allure服务{port}端口已开启")
============================= 提升自己 ==========================
进群交流、获取更多干货, 请关注微信公众号:
> > > 咨询交流、进群,请加微信,备注来意:sanshu1318 (←点击获取二维码)
> > > 学习路线+测试实用干货精选汇总:
https://www.cnblogs.com/upstudy/p/15859768.html
> > > 【自动化测试实战】python+requests+Pytest+Excel+Allure,测试都在学的热门技术:
https://www.cnblogs.com/upstudy/p/15921045.html
> > > 【热门测试技术,建议收藏备用】项目实战、简历、笔试题、面试题、职业规划:
https://www.cnblogs.com/upstudy/p/15901367.html
> > > 声明:如有侵权,请联系删除。
============================= 升职加薪 ==========================
更多干货,正在挤时间不断更新中,敬请关注+期待。
进群交流、获取更多干货, 请关注微信公众号:
> > > 咨询交流、进群,请加微信,备注来意:sanshu1318 (←点击获取二维码)
> > > 学习路线+测试实用干货精选汇总:
https://www.cnblogs.com/upstudy/p/15859768.html
> > > 【自动化测试实战】python+requests+Pytest+Excel+Allure,测试都在学的热门技术:
https://www.cnblogs.com/upstudy/p/15921045.html
> > > 【热门测试技术,建议收藏备用】项目实战、简历、笔试题、面试题、职业规划:
https://www.cnblogs.com/upstudy/p/15901367.html
> > > 声明:如有侵权,请联系删除。
============================= 升职加薪 ==========================
更多干货,正在挤时间不断更新中,敬请关注+期待。