Cra*_*000 4 python bash subprocess
要启动一个Python脚本(它是需要用于运行OLED显示器)从终端,我必须使用下面的bash命令:python demo_oled_v01.py --display ssd1351 --width 128 --height 128 --interface spi --gpio-data-command 20。之后的那些参数.py很重要,否则,脚本将使用默认设置运行,而在我的情况下,脚本将不会使用默认设置启动。因此,需要那些参数。
当我需要从另一个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'])
Run Code Online (Sandbox Code Playgroud)
在我的父脚本中,但出现错误说明:
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
我怀疑在--display ssd1351 --width 128 --height 128 --interface spi --gpio-data-command 20之后添加参数 .py可能会导致启动脚本困难。如前所述,这些参数对于我来说是必不可少的,包括在终端上使用bash命令启动时。如何使用带有必需参数的子进程来启动此脚本?
这最初是一个评论线程,但变得太长和复杂。
将 Python 作为 Python 的子进程调用是一种反模式。您通常可以通过重构 Python 代码来有效地避免这种情况,以便您的程序可以将另一个程序作为简单的库(或模块、包或其他什么)调用 - 这里有一些您需要的术语更正确地理解......最终)。
话虽如此,在某些情况下,子进程需要成为子进程(例如,它可能被设计为进行自己的信号处理),因此不要盲目应用这一点。
如果您有一个类似的脚本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()
Run Code Online (Sandbox Code Playgroud)
观察当您从命令行运行脚本时,它将__name__如何'__main__'进入main()将命令行分开的函数,然后调用其他函数 - 在本例中为real_demo(). 现在,如果您从已经运行的 Python 调用此代码,则无需真正将参数收集到列表中并将它们传递给新进程。只需让您的 Python 脚本加载您想要从脚本中调用的函数,并使用您的参数调用它即可。
换句话说,如果你目前正在做
subprocess.call(['demo.py', '--something', 'foo', '--other', value, '--message', 'whatever'])
Run Code Online (Sandbox Code Playgroud)
您可以将子流程调用替换为
from demo import real_demo
real_demo('foo', value, message='whatever')
Run Code Online (Sandbox Code Playgroud)
请注意您如何绕过该main()函数和所有丑陋的命令行解析,而只是调用另一个 Python 函数。(注意参数的顺序和名称;它们可能与命令行解析器接受的完全不同。)它是在不同的文件中定义的事实是一个小细节,import您处理的小细节,并且事实该文件包含其他函数,您可以忽略(或者,如果您想以方便的方式访问未通过命令行界面公开的内部函数,则可以更充分地利用)。
作为一种优化,Python 不会import重复执行某些操作,因此您确实需要确保您需要的功能在您import使用时不会运行。通常,您import在脚本的开头一次(尽管从技术上讲,您可以在def需要它的内部执行此操作,例如,如果您的代码中只有一个位置依赖于 )import,然后调用从中获得的函数根据您的需要多次import或多次。
这是对一个非常常见问题的快速回顾。如果这不能让您朝着正确的方向开始,您应该能够在 Stack Overflow 上找到有关此重构任务各个方面的许多现有问题。
添加 python 脚本的完整路径并分隔所有参数
前任:
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'])
Run Code Online (Sandbox Code Playgroud)
该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'])
Run Code Online (Sandbox Code Playgroud)
在此处查看有关Popen的更多信息。
| 归档时间: |
|
| 查看次数: |
4236 次 |
| 最近记录: |