bash 从另一个脚本启动一个 python 脚本,在子进程参数中使用参数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/48395685/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Launch a python script from another script, with parameters in subprocess argument
提问by Craver2000
To launch a python script (it is needed for running an OLED display) from terminal, I have to use the following bash commands: python demo_oled_v01.py --display ssd1351 --width 128 --height 128 --interface spi --gpio-data-command 20
. Those parameters after .py
are important, otherwise, the script will run with default settings and in my case, the script will not launch with default settings. Thus, those parameters are needed.
要启动一个Python脚本(它是需要用于运行OLED显示器)从终端,我必须使用下面的bash命令:python demo_oled_v01.py --display ssd1351 --width 128 --height 128 --interface spi --gpio-data-command 20
。后面.py
的参数很重要,否则脚本将使用默认设置运行,在我的情况下,脚本将不会使用默认设置启动。因此,需要这些参数。
The problem arises when I need to launch my script from another python script, (instead of using bash commands on terminal). To launch one of my python script from a parent script. I have used:
当我需要从另一个 python 脚本启动我的脚本时出现问题(而不是在终端上使用 bash 命令)。从父脚本启动我的 Python 脚本之一。我用过了:
import subprocess # to use subprocess
p = subprocess.Popen(['python', 'demo_oled_v01.py --display ssd1351 --width 128 --height 128 --interface spi --gpio-data-command 20'])
in my parent script but I got an error stating:
在我的父脚本中,但我收到一条错误消息:
python: can't open file 'demo_oled_v01.py --display ssd1351 --width 128 --height 128 --interface spi --gpio-data-command 20': [Errno 2] No such file or directory
python: can't open file 'demo_oled_v01.py --display ssd1351 --width 128 --height 128 --interface spi --gpio-data-command 20': [Errno 2] No such file or directory
I suspect that adding the parameters --display ssd1351 --width 128 --height 128 --interface spi --gpio-data-command 20
after .py
may be causing difficulty in launching the script. As mentioned, these parameters are otherwise essential for me to include for launching with bash commands on terminal. How can I use subprocess with the required parameters to launch this script?
我怀疑在--display ssd1351 --width 128 --height 128 --interface spi --gpio-data-command 20
之后添加参数 .py
可能会导致脚本启动困难。如前所述,这些参数对我来说是必不可少的,以便在终端上使用 bash 命令启动。如何使用具有所需参数的子进程来启动此脚本?
回答by Evan Rose
The subprocess
library is interpreting all of your arguments, including demo_oled_v01.py
as a single argument to python. That's why python is complaining that it cannot locate a file with that name. Try running it as:
该subprocess
库正在解释您的所有参数,包括demo_oled_v01.py
作为 python 的单个参数。这就是为什么 python 抱怨它找不到具有该名称的文件的原因。尝试将其运行为:
p = subprocess.Popen(['python', 'demo_oled_v01.py', '--display',
'ssd1351', '--width', '128', '--height', '128', '--interface', 'spi',
'--gpio-data-command', '20'])
See more information on Popen here.
在此处查看有关 Popen 的更多信息。
回答by tripleee
This started as a comment thread, but got too long and complex.
这开始是一个评论线程,但变得太长和复杂。
Calling Python as a subprocess of Python is an antipattern. You can often fruitfully avoid this by refactoring your Python code so that your program can call the other program as a simple library (or module, or package, or what have you -- there is a bit of terminologyhere which you'll want to understand more properly ... eventually).
将 Python 作为 Python 的子进程调用是一种反模式。您通常可以通过重构 Python 代码来有效地避免这种情况,这样您的程序就可以将另一个程序作为一个简单的库(或模块、包或您拥有的东西)调用——这里有一些术语,您需要更正确地理解......最终)。
Having said that, there arescenarios where the subprocess needsto be a subprocess (perhaps it is designed to do its own signal handling, for example) so don't apply this blindly.
话虽如此,在某些情况下,子进程需要成为子进程(例如,它可能被设计为进行自己的信号处理),因此不要盲目应用它。
If you have a script like demo.py
which contains something like
如果您有一个demo.py
包含类似内容的脚本
def really_demo(something, other, message='No message'):
# .... some functionality here ...
def main():
import argparse
parser = argparse.ArgumentParser(description='Basic boilerplate, ignore the details.')
parser.add_argument('--something', dest='something') # store argument in args.something
parser.add_argument('--other', dest='other') # ends up in args.other
# ... etc etc etc more options
args = parser.parse_args()
# This is the beef: once the arguments are parsed, pass them on
really_demo(args.something, args.other, message=args.message)
if __name__ == '__main__':
main()
Observe how when you run the script from the command line, __name__
will be '__main__'
and so it will plunge into the main()
function which picks apart the command line, then calls some other function -- in this case, real_demo()
. Now, if you are calling this code from an already running Python, there is no need really to collect the arguments into a list and pass them to a new process. Just have your Python script load the function you want to call from the script, and call it with your arguments.
观察当您从命令行运行脚本时,__name__
将如何'__main__'
,因此它将进入main()
分离命令行的函数,然后调用其他一些函数——在本例中为real_demo()
. 现在,如果您从已经运行的 Python 中调用此代码,则无需真正将参数收集到列表中并将它们传递给新进程。只需让您的 Python 脚本加载您想要从脚本中调用的函数,并使用您的参数调用它。
In other words, if you are currently doing
换句话说,如果你目前正在做
subprocess.call(['demo.py', '--something', 'foo', '--other', value, '--message', 'whatever'])
you can replace the subprocess call with
您可以将子进程调用替换为
from demo import real_demo
real_demo('foo', value, message='whatever')
Notice how you are bypassing the main()
function and all the ugly command-line parsing, and simply calling another Python function. (Pay attention to the order and names of the arguments; they may be quite different from what the command-line parser accepts.) The fact that it is defined in a different file is a minor detail which import
handles for you, and the fact that the file contains other functions is something you can ignore (or perhaps exploit more fully if, for example, you want to access internal functions which are not exposed via the command-line interface in a way which is convenient for you).
请注意您如何绕过该main()
函数和所有丑陋的命令行解析,而只是调用另一个 Python 函数。(注意参数的顺序和名称;它们可能与命令行解析器接受的完全不同。)它在不同的文件中定义的事实是import
为您处理的一个次要细节,并且事实上该文件包含的其他功能是您可以忽略的(或者,如果您想以一种对您方便的方式访问未通过命令行界面公开的内部功能,则可以更充分地利用)。
As an optimization, Python won't import
something twice, so you really need to make sure the functionality you need is not run when you import
it. Commonly, you import
once, at the beginning of your script (though technically you can do it inside the def
which needs it, for example, if there is only one place in your code which depends on the import
) and then you call the functions you got from the import
as many or as few times as you need them.
作为一种优化,Python 不会import
重复执行某些操作,因此您确实需要确保您需要的功能在您运行时不会运行import
。通常,您import
曾经在脚本的开头(尽管从技术上讲,您可以在def
需要它的地方执行此操作,例如,如果您的代码中只有一个位置取决于import
),然后您调用从中获得的函数在import
尽可能多或尽可能少的时间,你需要他们。
This is a lightning recap of a very common question. If this doesn't get you started in the right direction, you should be able to find many existing questions on Stack Overflow about various aspects of this refactoring task.
这是一个非常常见的问题的闪电般的回顾。如果这不能让您朝着正确的方向开始,您应该能够在 Stack Overflow 上找到许多关于此重构任务各个方面的现有问题。
回答by Rakesh
Add full path to the python script & separate all parameter
添加python脚本的完整路径并分隔所有参数
EX:
前任:
import subprocess
p = subprocess.Popen(['python', 'FULL_PATH_TO_FILE/demo_oled_v01.py', '--display', 'ssd1351', '--width', '128', '--height', '128', '--interface', 'spi', '--gpio-data-command', '20'])
回答by Paul Denoyes
For Windowsand Python 3.x, you could :
对于Windows和Python 3.x,您可以:
- Use a Windows shell (cmd.exe most probably on Windows by default)
- 使用 Windows shell(默认情况下,cmd.exe 很可能在 Windows 上)
result = subprocess.Popen('cd C:\Users\PathToMyPythonScript
&& python myPythonScript.py value1ofParam1 value2ofParam2',
shell=True, universal_newlines=True,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
output, error = result.communicate()
print(output)
- Stay in your Python environment (remove shell=True) you can write :
- 留在您的 Python 环境中(删除 shell=True),您可以编写:
result = subprocess.Popen(["C:\Windows\System32\cmd.exe", "/k",
"cd", "C:\Users\PathToMyPythonScript",
"&&", "dir", "&&", "python", "myPythonScript.py",
"value1ofParam1", "value2ofParam2"], universal_newlines=True,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
output, error = result.communicate()
print(output)
- Example of script file you can call for a try (the "MyPythonScript.py") :
- 您可以尝试调用的脚本文件示例(“MyPythonScript.py”):
# =============================================================================
# This script just outputs the arguments you've passed to it
import sys
print('Number of arguments:', len(sys.argv), 'arguments.')
print('Argument List:', str(sys.argv))
# =============================================================================