[英]Call command-line oriented script from another python script
I am using a script written in Python that uses the argparse module to get it's arguments from command line. 我使用的是用Python编写的脚本,它使用argparse模块从命令行获取它的参数。 I try to modify this file as less as possible as various people work on it. 我尝试尽可能少地修改此文件,因为各种人都在使用它。
Ex: script is called CLscript.py and I call it with 例如:脚本名为CLscript.py,我用它来调用它
python CLscript.py -option1 arg1 -flag1 -option2 arg2
But I'm facing the case where I would like to automate things one level higher and automatically launch this script with wide range of script-generated arguments. 但我面临的情况是,我希望自动化更高级别的东西,并使用各种脚本生成的参数自动启动此脚本。
I would like to keep using all the existing organisation of options and flags available in this script. 我想继续使用此脚本中现有的所有选项和标志组织。
For example, when I run CLscript.py from topLevelScript.py through : 例如,当我从topLevelScript.py运行CLscript.py时:
subprocess.call("python CLscript.py -option1 arg1 -flag1 -option2 arg2")
,and I see from the output that something is going wrong, I stop the execution topLevelScript.py, but CLscript.py continue to run independently in another python process that I Have to kill manually. ,我从输出中看到出现问题,我停止执行topLevelScript.py,但CLscript.py继续在另一个我必须手动杀死的python进程中独立运行。 I cannot neither launch topLevelScript.py in debug mode to stop at a breakpoint in CLscript.py. 我无法在调试模式下启动topLevelScript.py以在CLscript.py中的断点处停止。
I would like to do this all from inside python, without building a command line string and launching CLscript.py with a subprocess. 我想从python内部完成所有这些操作,无需构建命令行字符串并使用子进程启动CLscript.py。 Every call would remains attached to the same original launch, just like a function call, and not creating multiple python threads like it would do with a subprocess.call() . 每个调用都将保持附加到同一个原始启动,就像函数调用一样,而不是像使用subprocess.call()那样创建多个python线程。
Something like passing a list of string with options, flags and arguments somehow to the script maybe? 有点像是以某种方式向脚本传递带有选项,标志和参数的字符串列表吗?
Is there something like 有没有类似的东西
import CLscript.py
CLsimulator(CLscript,["-option1",arg1,"-flag1","-option2",arg2])
Would something like this work? 会这样的吗? Extract most of your code into a new function that expects arguments similar to the ones you send in via the command line. 将大部分代码提取到一个新函数中,该函数需要与通过命令行发送的参数类似的参数。 Then write a new function that gathers the command line arguments and sends them to the first function ... 然后编写一个新函数,收集命令行参数并将它们发送到第一个函数...
def main(foo, bar):
a = foo + bar
print a
def from_command_line():
foo, bar = get_command_line_args()
main(foo, bar)
if __name__ == "__main__":
from_command_line()
Then your other scripts can just call the main function. 然后你的其他脚本可以调用main函数。
First of all, use http://docs.python.org/2/library/subprocess.html#subprocess.Popen and not subprocess.call()
: 首先,使用http://docs.python.org/2/library/subprocess.html#subprocess.Popen而不是subprocess.call()
:
import subprocess
child = subprocess.Popen(
['python', 'CLscript.py', '-option1', 'arg1', '-flag1', '-option2', 'arg2'],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
Please notice that as the first argument you pass an array of strings
just like you want. 请注意,作为第一个参数,您可以按照自己的意愿传递array of strings
。
Secondly redirection of standard file descriptors will be important. 其次,重定向标准文件描述符非常重要。 See http://docs.python.org/2/library/subprocess.html#subprocess.PIPE . 请参见http://docs.python.org/2/library/subprocess.html#subprocess.PIPE 。
Now you have child
variable which holds instance of Popen
class. 现在你有了一个child
变量,它包含了Popen
类的实例。
What you can do with this instance? 你可以用这个实例做什么?
# Check if child is terminated and possibly get the returncode
child.poll()
# Write to child's standard input by a file-like object accessible with
child.stdin
# Read child's standard output and standard error by file-like objects accesible with
child.stdout
child.stderr
You said you wanted to detect if something goes wrong in the child process from it's output. 你说你想从它的输出中检测子进程中是否出现问题。
Don't you find stdout
and stderr
quite useful for this case? 难道你不觉得stdout
和stderr
对这个案子非常有用吗?
Now you wanted to terminate the child if you detected that something went wrong. 现在你想要在发现问题出现时终止孩子。
child.kill()
child.terminate()
child.send_signal(signal)
If in the end you are sure that everything went well but you want to let child finalize normally, you should use 如果你最终确定一切顺利,但你想让孩子正常完成,你应该使用
child.wait()
or even better 甚至更好
child.communicate()
because communicate
will handle lots of output properly. 因为communicate
会正确处理大量输出。
Good luck! 祝好运!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.