繁体   English   中英

从另一个脚本启动一个 python 脚本,在子进程参数中使用参数

[英]Launch a python script from another script, with parameters in subprocess argument

要从终端启动 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'])

在我的父脚本中,但我收到一条错误消息:

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

我怀疑在.py之后添加参数--display ssd1351 --width 128 --height 128 --interface spi --gpio-data-command 20可能会导致脚本启动困难。 如前所述,这些参数对我来说是必不可少的,以便在终端上使用 bash 命令启动。 如何使用具有所需参数的子进程来启动此脚本?

subprocess库解释所有的参数,包括demo_oled_v01.py作为一个参数传递给蟒蛇。 这就是为什么 python 抱怨它找不到具有该名称的文件的原因。 尝试将其运行为:

p = subprocess.Popen(['python', 'demo_oled_v01.py', '--display',
'ssd1351', '--width', '128', '--height', '128', '--interface', 'spi',
'--gpio-data-command', '20'])

此处查看有关 Popen 的更多信息。

这开始是一个评论线程,但变得太长和复杂。

将 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()

观察当您从命令行运行脚本时, __name__将是'__main__' ,因此它将进入main()函数,该函数将命令行分开,然后调用其他一些函数——在本例中为real_demo() . 现在,如果您从已经运行的 Python 中调用此代码,则无需真正将参数收集到列表中并将它们传递给新进程。 只需让您的 Python 脚本加载您想要从脚本中调用的函数,并使用您的参数调用它。

换句话说,如果你目前正在做

 subprocess.call(['demo.py', '--something', 'foo', '--other', value, '--message', 'whatever'])

您可以将子进程调用替换为

 from demo import real_demo
 real_demo('foo', value, message='whatever')

请注意您如何绕过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'])

对于WindowsPython 3.x ,您可以:

  1. 使用 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)
  1. 留在您的 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)

  • 您可以尝试调用的脚本文件示例(“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))
# =============================================================================

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM