我正在编写一个Python脚本,时间有点紧。有些操作我在bash中很熟悉,所以我想知道如何将一些bash命令嵌入到Python脚本中。
谢谢
我正在编写一个Python脚本,时间有点紧。有些操作我在bash中很熟悉,所以我想知道如何将一些bash命令嵌入到Python脚本中。
谢谢
最佳的做法:
def run_script(script, stdin=None):
"""Returns (stdout, stderr), raises error on non-zero return code"""
import subprocess
# Note: by using a list here (['bash', ...]) you avoid quoting issues, as the
# arguments are passed in exactly this order (spaces, quotes, and newlines won't
# cause problems):
proc = subprocess.Popen(['bash', '-c', script],
stdout=subprocess.PIPE, stderr=subprocess.PIPE,
stdin=subprocess.PIPE)
stdout, stderr = proc.communicate()
if proc.returncode:
raise ScriptException(proc.returncode, stdout, stderr, script)
return stdout, stderr
class ScriptException(Exception):
def __init__(self, returncode, stdout, stderr, script):
self.returncode = returncode
self.stdout = stdout
self.stderr = stderr
Exception().__init__('Error in script')
-c
? - alper-c
告诉bash执行字符串。因此,bash "echo hi"
将尝试执行名为"echo hi"的脚本文件(这是行不通的!),而bash -c "echo hi"
将尝试运行"echo hi"(并显示"hi")。 - Ian Bickingimport os
os.system('command')
如果你有一个很长的命令,或者一组命令,你可以使用变量。 例如:
# this simple line will capture column five of file.log
# and then removed blanklines, and gives output in filtered_content.txt.
import os
filter = "cat file.log | awk '{print $5}'| sed '/^$/d' > filtered_content.txt"
os.system(filter)
Is
import os
os.system ("bash -c 'echo $0'")
你要我为你做什么?
编辑:关于易读性
当然,你可以让它更易读。
import os
script = """
echo $0
ls -l
echo done
"""
os.system("bash -c '%s'" % script)
import os
def sh(script):
os.system("bash -c '%s'" % script)
sh("echo $0")
sh("ls -l")
sh("echo done")
当bash命令简单且没有括号、逗号和引号时,子进程(subprocess)和os.system()运行良好。嵌入复杂的bash参数的简单方法是在Python脚本末尾添加bash脚本,并使用带有唯一字符串注释的简单os.system()命令来tail并转换为bash文件。
#!/usr/bin/python
## name this file "file.py"
import os
def get_xred(xx,yy,zz):
xred=[]
####gaur###
xred.append([ zz[9] , zz[19] , zz[29] ])
xred.append([ zz[9] , xx[9] , yy[9] ])
xred.append([ zz[10], zz[20] , zz[30] ])
xred.append([ zz[10], xx[10] , yy[10] ])
###nitai###
xred=np.array(xred)
return xred
## following 3 lines executes last 6 lines of this file.
os.system("tail -n 6 file.py >tmpfile1")
os.system("sed 's/###123//g' tmpfile1>tmpfile2")
os.system("bash tmpfile2")
###### Here ###123 is a unique string to be removed
###123#!/bin/sh
###123awk '/###gaur/{flag=1;next}/###nitai/{flag=0} flag{print}' file.py >tmp1
###123cat tmp1 | awk '{gsub("xred.append\\(\\[","");gsub("\\]\\)","");print}' >tmp2
###123awk 'NF >0' tmp2 > tmp3
###123sed '$d' tmp3 |sed '$d' | sed '$d' >rotation ; rm tmp*
我创建了Sultan来解决你正在尝试做的事情。它没有任何外部依赖,并且尽可能地轻巧,并提供一个Pythonic接口到Bash。
@Ian Bicking
的回答很有用,但它只允许我们运行脚本。相反,我们可以想出一种更灵活的代码,可以运行命令。我有一个不同的方法。
#!/usr/bin/env python3
from subprocess import Popen, PIPE
class BashCommandsException(Exception):
def __init__(self, returncode, output, error_msg):
self.returncode = returncode
self.output = output
self.error_msg = error_msg
Exception.__init__('Error in executed command')
def popen_communicate(cmd, stdout_file=None):
"""Acts similir to lib.run(cmd) but also returns the output message captures on
during the run stdout_file is not None in case of nohup process writes its
results into a file
"""
cmd = list(map(str, cmd)) # all items should be string
if stdout_file is None:
p = Popen(cmd, stdout=PIPE, stderr=PIPE)
else:
with open(stdout_file, "w") as outfile:
# output written into file, error will be returned
p = Popen(cmd, stdout=outfile, stderr=PIPE, universal_newlines=True)
output, error = p.communicate()
p.wait()
return p, output, error
output, error = p.communicate()
output = output.strip().decode("utf-8")
error = error.decode("utf-8")
return p, output, error
def run(cmd):
log_file = "/tmp/log.txt"
# if log_file is not provided returned output will be stored in output
p, output, error_msg = popen_communicate(cmd, log_file)
if p.returncode != 0:
raise BashCommandsException(p.returncode, output, error_msg, str(cmd))
return output
if __name__ == "__main__":
# This could be any command you want to execute as you were in bash
cmd = ["bash", "script_to_run.sh"]
try:
run(cmd)
except Exception as e:
print(e)
还有commands
模块可以更好地控制输出:
https://docs.python.org/2/library/commands.html