1 python命令行参数

1.1 基本语法

一、代码use.py

import sys
print("脚本名:",sys.argv[0])
print("参数1:",sys.argv[1])

二、命令行python3 use.py “lucy”

脚本名: use.py
参数1: lucy

1.2 宿主机实例

将json字符串作为命令行参数传递。

1.2.1 use.py

# -*- coding: UTF-8 -*-
import sys
if __name__ == "__main__":
    print("receive",sys.argv[1])

1.2.2 main.py

# -*- coding: UTF-8 -*-
import subprocess
import json
data_dict = {'name':'lucy'}
data_json = json.dumps(data_dict, separators=(',', ':')) # 去掉格式化后的空格
cmd_str = "python use.py {}".format(data_json)
print(cmd_str)
re = subprocess.getoutput(cmd_str)
print(re)

输出如下:

python use.py {"name":"lucy"}
receive {name:lucy}

sys.argv会对输入的参数进行转义,传递的双引号被自动删除。

1.3 命令行传递json

1.3.1 use.py

# -*- coding: UTF-8 -*-
import sys
if __name__ == "__main__":
    print("receive",sys.argv[1])

1.3.2 main.py

# -*- coding: UTF-8 -*-
# -*- coding: UTF-8 -*-
import subprocess
import json
data_dict = {'name':'lucy',
             "starttime":"2022-11-14 07:20:23.654"}
data_json = json.dumps(data_dict) # 第一次序列化
print("第一次序列化",data_json)
data_json = json.dumps(data_json) # 第二次序列化,加上转义字符
print("第二次序列化",data_json)
cmd_str = "python use.py {}".format(data_json)
print(cmd_str)
re = subprocess.getoutput(cmd_str)
print("GET",re)

输出如下:

第一次序列化 {"name": "lucy", "starttime": "2022-11-14 07:20:23.654"}
第二次序列化 "{\"name\": \"lucy\", \"starttime\": \"2022-11-14 07:20:23.654\"}"
python use.py "{\"name\": \"lucy\", \"starttime\": \"2022-11-14 07:20:23.654\"}"
GET receive {"name": "lucy", "starttime": "2022-11-14 07:20:23.654"}

2 subprocess模块详解

subprocess是Python与系统交互的一个库,该模块允许生成新进程,连接到它们的输入/输出/错误管道,并获取它们的返回代码。

该模块旨在替换几个较旧的模块和功能:

os.system
os.spawn
os.popen
popen2
commands

运行python的时候,我们都是在创建并运行一个进程。

linux中一个进程可以fork一个子进程,并让这个子进程exec另外一个程序。

在python中,我们通过标准库中的subprocess包来fork一个子进程,并且运行一个外部的程序。

subprocess包中定义有数个创建子进程的函数,这些函数分别以不同的方式创建子进程,我们可以根据需要来从中选取一个使用。

subprocess还提供了一些管理标准流(standard stream)和管道(pipe)的工具,从而在进程间使用文本通信

使用subprocess启动电脑的子进程。

subprocess模块,允许你生成新的进程,连接它们的输入、输出、错误管道,并且获取它们的返回码。

python调用带参数的shell脚本 python脚本获取参数_python调用带参数的shell脚本

2.1 旧有模块的使用

2.1.1 os.system()

执行操作系统的命令,将结果输出到屏幕,只返回命令执行状态(0:成功,非 0 :失败)。

import os
re = os.system("ls")
print("下面的是返回的内容")
print(type(re))
print(re)

结果自动输出到屏幕。0表示执行成功。

python调用带参数的shell脚本 python脚本获取参数_子进程_02

2.1.2 os.popen()

执行操作系统的命令,会将结果保存在内存当中,可以用read()方法读取出来。

import os
re = os.popen("ls")
print("下面的是返回的内容")
print(type(re))
print(re)
print(re.read())

结果保存在内存当中。

python调用带参数的shell脚本 python脚本获取参数_子进程_03


当需要得到外部程序的输出结果时,本方法非常有用,返回一个类文件对象,调用该对象的read()或readlines()方法可以读取输出内容。

os.popen(cmd) 要得到命令的输出内容,只需再调用下read()或readlines()等 如a=os.popen(cmd).read()

文件test.py

import sys
x = sys.stdin
for line in x:
    print("receive",line)
    break # 执行一次后退出循环,否则会一直持续等待运行

文件main.py

import os
a = "hello"
zz = os.popen("echo {}| python test.py".format(a)).read()
print(zz)

2.2 subprocess模块

2.2.1 subprocess.run()

import subprocess
re = subprocess.run("ls -al",shell=True)
print(type(re))
print(re)

(1)python解析,则传入命令的每个参数的列表
re = subprocess.run(["ls","-al"])

(2)Linux shell解析,则传入命令字符串,并且shell=True
re = subprocess.run("ls -al",shell=True)

python调用带参数的shell脚本 python脚本获取参数_json_04

2.2.2 subprocess.call()

执行命令,返回命令的结果和执行状态,0或者非0。

import subprocess
re = subprocess.call("ls -l",shell=True)
print(type(re))
print(re)

0表示执行成功。

python调用带参数的shell脚本 python脚本获取参数_json_05

2.2.3 subprocess.check_call()

执行命令,返回结果和状态,正常为0 ,执行错误则抛出异常。

import subprocess
re = subprocess.check_call("ls -l",shell=True)
print(type(re))
print(re)

python调用带参数的shell脚本 python脚本获取参数_子进程_06

2.2.4 subprocess.getstatusoutput()

接受字符串形式的命令,返回 一个元组形式的结果,第一个元素是命令执行状态,第二个为执行结果。

import subprocess
re = subprocess.getstatusoutput("pwd")
print(type(re))
print(re)

python调用带参数的shell脚本 python脚本获取参数_python调用带参数的shell脚本_07

2.2.5 subprocess.getoutput()

接受字符串形式的命令,查看执行结果。

import subprocess
re = subprocess.getoutput("pwd")
print(type(re))
print(re)

python调用带参数的shell脚本 python脚本获取参数_json_08

2.2.6 subprocess.check_output()

执行命令,返回执行的结果,而不是打印。

import subprocess
re = subprocess.check_output("pwd")
print(type(re))
print(re)

结果以字节形式返回。

python调用带参数的shell脚本 python脚本获取参数_python_09

2.3 subprocess.Popen()

其实以上subprocess使用的方法,都是对subprocess.Popen的封装,下面我们就来看看这个Popen方法。

2.3.1 stdout标准输出

python调用带参数的shell脚本 python脚本获取参数_子进程_10

2.3.2 stderr标准错误

python调用带参数的shell脚本 python脚本获取参数_python调用带参数的shell脚本_11


注意:上面的提到的标准输出都为啥都需要等于subprocess.PIPE,这个又是啥呢?原来这个是一个管道。

2.3.3 poll()

定时检查命令有没有执行完毕,执行完毕后返回执行结果的状态,没有执行完毕返回None。

python调用带参数的shell脚本 python脚本获取参数_json_12

2.3.4 wait()

等待命令执行完成,并且返回结果状态。

python调用带参数的shell脚本 python脚本获取参数_python调用带参数的shell脚本_13

2.3.5 terminate()

结束进程。

python调用带参数的shell脚本 python脚本获取参数_python_14

2.3.6 pid

获取当前执行子shell的程序的进程号。

python调用带参数的shell脚本 python脚本获取参数_python调用带参数的shell脚本_15

3 应用

stdin输入打开的文件。
communicate">Popen.communicate

3.1 交互方式一run传参到std

3.1.1 use.py

import sys
if __name__ == "__main__":
    x = sys.stdin # 从标准输入获取数据
    for line in x:
        print("标准输入的数据",line)
        break # 执行一次之后跳出循环

3.1.2 log.txt

你好

3.1.3 main.py

import subprocess
re = subprocess.run("python3 use.py",stdin = open("log.txt","rb"),shell=True)

3.2 交互方式二popen传参到std

3.2.1 aa_call.py

# -*- coding: UTF-8 -*-
import subprocess
import json
import sys

msg_dict = {
    "beginTime":"2022-11-25 17:32:03.460",# 开始时间
    "overTime":"2022-11-26 17:32:03.460",# 结束时间
}
msg = json.dumps(msg_dict, separators=(',', ':'),ensure_ascii=False)

child1 = subprocess.Popen("python aa_main.py",shell=True,stdin=subprocess.PIPE,stdout=subprocess.PIPE)
re = child1.communicate(msg.encode("utf-8"))
re = re[0].decode("utf-8")

print("主进程",re)
zz = json.loads(re)
print(zz)

3.2.2 aa_main.py

# -*- coding: UTF-8 -*-
import sys
if __name__ == "__main__":
    line = sys.stdin.readline()
    print(line)

3.3 传参到sys.argv

3.3.1 test_call.py

# -*- coding: UTF-8 -*-
import sys
import subprocess
import json
msg_dict = {
    "steps":[{"innerTag": "GAP_ACT","step":5},{"innerTag": "GAP_SET","step":10}],
    "calMode":1,
    "inscode":"ins6115",
    "algcode":"b_011",
    "beginTime":"2022-11-24 17:32:03.460",
    "overTime":"2022-11-25 17:32:03.460",
    "windowType":0,
    "window":20,
    "slide":10,
    "triggercountset":1,
    "mode_msg":[{'name': '逻辑条件1', 'value': '≥'}, {'name': '逻辑条件2', 'value': '≥'}],
    "thdIn":[{'name': '数据阈值', 'thdParamKey': 'thd_param_数据阈值', 'value': '20'}, {'name': '持续超限阈值', 'thdParamKey': 'thd_param_持续超限阈值', 'value': '2'}]
}

msg = json.dumps(msg_dict, separators=(',', ':')) # 中文默认使用gbk编码
print("替换前",msg)
msg = msg.replace('"','\\"')
print("替换后",msg)
cmd_str = "python aa_use.py {}".format(msg)
print(cmd_str)
re = subprocess.getoutput(cmd_str)
print(re)

3.3.2 aa_use.py

存在空格的话,传参会被拆分成多个变量,所以用空格进行拼接。

# -*- coding: UTF-8 -*-
import sys
import json
if __name__ == '__main__':
    aa = " ".join(sys.argv[1:])
    aa = json.dumps(aa)
    bb = json.loads(aa)
    out_dict ={"接收":bb}
    print(json.dumps(out_dict))

3.3.3 命令行验证方式

注意外边的引号不要去掉。

python3 aa_use.py  "{\"steps\":[{\"innerTag\":\"690614M05*00*F4_WS_ROLLGAP_ACT\",\"step\":5},{\"innerTag\":\"690614M05*00*F4_WS_ROLLGAP_SET\",\"step\":10}]}"