从另一个脚本启动python脚本,子进程参数中包含参数

时间:2018-01-23 06:45:29

标签: 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'])

在我的父脚本中但是我收到一条错误说明:

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命令启动。如何使用带有所需参数的子进程来启动此脚本?

4 个答案:

答案 0 :(得分:4)

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'])

查看有关Popen here的更多信息。

答案 1 :(得分:3)

添加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'])

答案 2 :(得分:2)

这开始是一个评论主题,但是太长而且复杂。

将Python作为Python的子进程调用是一种反模式。您通常可以通过重构Python代码来有效地避免这种情况,以便您的程序可以将其他程序作为一个简单的库(或模块,或包,或者您拥有的内容)调用 - 这里有一些terminology #39;想要更正确地理解......最终)。

话虽如此,场景,其中子进程需要作为子进程(例如,它可能是为了自己的信号处理而设计的)所以不要&# 39;盲目地应用它。

如果您有像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时不运行所需的功能。通常,您{1}}一次,在脚本的开头(虽然从技术上讲,您可以在需要它的import内执行此操作,例如,如果代码中只有一个地方依赖于def)然后根据需要调用import中的函数。

这是一个非常常见问题的闪电概述。如果这并没有让您开始朝着正确的方向前进,那么您应该能够在Stack Overflow上找到关于此重构任务的各个方面的许多现有问题。

答案 3 :(得分:0)

对于 Windows Python 3.x ,您可以:

  1. 使用Windows shell(默认情况下,很可能在Windows上使用cmd.exe)
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))
# =============================================================================