我有一个中等大小的python脚本,可以从内部执行很多shell命令。我想在执行之前将所有这些命令打印到屏幕,以便我可以跟踪python脚本的控制流。
现在,该脚本使用多个命令来实际执行shell命令,包括来自os模块的system(),以及来自子进程模块的call(),popen()和check_output()。最简单的方法是什么?
我在考虑一个在执行它之前打印shell命令参数的包装函数,但我不知道如何编写一个可以根据用户自行决定调用正确的调用/ Popen或其他命令的泛型函数。我们还必须记住,这些调用涉及不同数量和类型的参数。
谢谢!
答案 0 :(得分:1)
为您要拦截的各种电话构建并安装decorator。因为即使“内置”函数是一流的对象,您也可以用日志版本替换它们:
import os
def log_wrap(f):
def logging_wrapper(*args, **kwargs):
print("Calling {} with args: {!r}, kwargs: {!r}".format(f.__name__, args, kwargs))
return f(*args, **kwargs)
return logging_wrapper
os.system("echo 'Hello, world!'")
os.system = log_wrap(os.system)
os.system("echo 'How do you like me now?!'")
此代码在运行时(python3)打印:
$ python test.py
Hello, world!
Calling system with args: ("echo 'How do you like me now?!'",), kwargs: {}
How do you like me now?!
请注意,在对os.system
的第一次和第二次调用之间,我将os.system
函数替换为在将参数传递给原始函数之前打印日志消息的函数。您可以将日志消息打印到文件,或者(更好)调用logging
模块,或调用pdb
调试器,或任何您喜欢的...
答案 1 :(得分:0)
由于你想要启动子进程,但是记录你的行为,你需要记录子进程stdout,stderr,
import subprocess as sp
import datetime
dt=datetime.datetime.now().strftime("%Y%m%d%H%M00")
ofd = open("res.sql","w+")
efd = open("log/cmd-{}.log".format(dt),"a+")
假设您正在构建一个命令(例如,mysqldump),并且您已加载数据库,表和凭证文件名(db,tbl,cnf)。您想打印即将执行的命令,
args = ["mysqldump","--defaults-extra-file="+cnf,"--single-transaction","--quick",db,tbl]
print " ".join(args)
现在,假设您已打开上面的输出和错误文件(ofd,efd),
proc = sp.Popen(args, shell=False, stdin=sp.PIPE, stdout=ofd, stderr=efd)
stdout,stderr = proc.communicate
rc = proc.wait()
if rc>0: print "error",rc,"dbdump failed"
else: print "result",stdout,stderr
记得关闭,efd。
答案 2 :(得分:0)
import commands
commands = r'''find .'''
result = commands.getstatusoutput(command)[0]
print("Command: {}\nresult: {}".format(command,result))