【问题标题】:Python: Running a script A that handles argparser inside script BPython:运行脚本 A 处理脚本 B 中的 argparser
【发布时间】:2016-09-30 03:14:06
【问题描述】:

我有一个 script_A,它使用 argparser 处理不同的输入,我用它来执行一个函数。我现在需要脚本 B 来调用并让所有脚本 A 从内部运行(让它处理不同的输入)。我正在使用 Windows。

目标: Script_B 将根据 script_A 的输出做进一步的分析。 Script_A 的行为根据传递的参数选项而改变。 Script_B 的行为始终相同。我宁愿不要把 script_A 和 script_B 组合成一个庞大的脚本。

目标已更新:为了让 script_B 正常工作,我需要运行 script_A,然后传递其中一个字典,即字典 D,它被计算(从 A 输出)传递给B. 直到所有 script_A 运行后才计算字典。

这就是 Script_A 的样子

import sys
import os
from argparse import ArgumentParser

def function 1:
    #it does stuff....

def function 2:
    #it does other stuf...

if __name__ == "__main__":
    parser = ArgumentParser(description = "functionA.py -i [--print]
    parser.add_argument('-i', '--id', help="Please write A or B", required=True)
    parser.add_argument('-r', '--re', help="Please write C or D, required=True)

    sysargs = parser.parse_args()

    #Variable definitions

    if str(sysargs.id) == "A":
        #Uses file A located in directory X to perform analysis
        #calls function A to perform analysis
    elif str(sysargs.id) == "B":
        #Uses file B located in Directory Y to perform analysis
        #calls function B to perform analysis

    if str(sysargs.re) == "C"
        #Provides thorough printout of analysis (more in depth for debugging)
    if str(sysargs.re) == "D"
        #Does Nothing (no debugging option)

脚本 A 运行良好,当我使用它时它就完成了它的工作。我使用命令行参数提交输入,这是必需的,有时是可选的。

这就是脚本B,我试过以下:

1

import sys
import numpy as np
import os
import script_A

os.system("script_A.py", -i "A" -r "C")

#Other stuff that script B does

2

import sys
import os
import script_A

exec(script_A.py[-i "A" -r "C"])

#Other stuff that script B does

3

import os
import sys
from subprocess import call

subprocess.call("script_A.py", -i "A" -r "C")

#Other stuff that script B does

我看过这里:Calling an external command in Python

这里:importing a python script from another script and running it with arguments

但无法从他们所说的内容中弄清楚。任何帮助是极大的赞赏。我还是 Python 的初学者。

我基于 cmets 尝试了以下方法:

1

import subprocess
import script_A

p.subprocess.Popen("script_A.py", "-i", "A", "-r", "none", shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)


(stdoutput, erroutput) = p.communicate()

TypeError: __init_() 为关键字参数“stdout”获取了多个值

我尝试添加 self 参数,但出现以下错误

p.subprocess.Popen("script_A.py", "-i", "A", "-r", "C", shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

TypeError: __init_() 为关键字参数“stderr”获得了多个值

2

import subprocess
import script_A

process= Popen(["script_A", "-i", "A", "-r", "C"], stdout = subprocess.PIPE, stderr=subprocess.STDOUT)

output = process.communicate()

OSError: [ERRno2] 没有这样的文件或目录

在执行子进程中转到 /subprocess.py 的目录出错

引发 child_exception

我不知道这是什么意思。

【问题讨论】:

  • 为什么需要通过命令行传递参数?只需import直接调用函数。
  • 抱歉,您能详细说明一下吗?只是为了澄清我不需要从脚本 B 中的脚本 A 运行单独的函数。我需要运行整个事情。我还想灵活地解析参数,以便在我想要显示更多输出时与何时不显示。
  • 那么这些替代品做什么(或不做什么)?你期待发生什么?如果您不直接使用它的功能(如在os.system 版本中),则不需要import script_A
  • 在您使用argparse 时,您不需要str(sysargs.id)args=parser.parse_args()if args.id == 'A':... 应该足够了。
  • 哎呀,抱歉 hpaulj 我确实在脚本 A 中有 args = parser.parse_args()。让我现在添加它。它仍然不适用于该行。我将在下一次编辑中详细说明替代方案。谢谢

标签: python shell command-line argparse


【解决方案1】:
p = subprocess.Popen("your_a_code_with_args_here",
                     shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

(stdoutput, erroutput) = p.communicate()

那么你的 B 代码就可以根据 A 代码的输出来做事了。

【讨论】:

  • 非常感谢您的建议。我试过了,它不工作。我遇到了一些麻烦。我已经更新了我的问题描述以反映我现在看到的情况。我想传递一个在整个脚本运行后制作的字典。
  • 不知道如何用管道交换python对象。也许你不能只返回 python 对象,使用 json.dumps 编码你的对象并返回;而您的 B 代码可以使用 json.loads 来解码 json 字符串并从代码 A 中获取真正的 python 对象。
【解决方案2】:

我已将您的A 压缩为:

import argparse

def function_1():
    print('function 1')

def function_2():
    print('function 2')

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument('-i', '--id', choices=['A','B'], default='A')
    parser.add_argument('-r', '--re', choices=['C','D'], default='C')

    args = parser.parse_args()

    #Variable definitions

    if args.id == "A":
        print("A")
        function_1()
    elif args.id == "B":
        print('B')
        function_2()
    if args.re == "C":
        print('C')
    if args.re == "D":
        print('D')

如果B

import os
os.system("python3 stack37557027_A.py -i A -r C")

然后A 运行并显示

A
function 1
C

使用main 块,import stack375570237_A 所做的只是从 B 导入两个可以运行的函数

stack375570237_A.function_A()

如果不清楚,请重新阅读有关if __name__ == "__main__": 用途的文档以及运行脚本和导入模块之间的区别。这是重要的基础 Python。

根据@atline 的建议:

import subprocess

p = subprocess.Popen("python3 stack37557027_A.py -i A -r C",
                     shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

(stdoutput, erroutput) = p.communicate()
print(stdoutput)
#print(erroutput)

显示是:

b'A\nfunction 1\nC\n'
#None

同样的东西,但包装成字节串。

请注意,在这两种情况下,我都使用一个字符串调用脚本,其中包括文件名和参数。

p = subprocess.Popen(["python3", "stack37557027_A.py", "-i", "A", "-r", "C"],
                 stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

这也有效。 shell 不再是 True,我使用的是字符串列表。

您可能需要查看subprocess 的文档。 https://pymotw.com/2/subprocess/

======================

您更新后的目标是:

,我需要运行 script_A,然后传递其中一个字典,即字典 D,它被计算(从 A 输出)传递给 B。T

一个问题是目前使用的方法要么只是将一个字符串显示到标准输出,要么将一个字符串返回给调用者(从标准输出)。它们不会像字典那样返回 Python 对象。

这本字典是在您的A 中的哪个位置生成的?它如何依赖于argparse 选项?

让我们改变 A 以便身体中的一个函数产生一个字典

def function_1(id, re):
    print('function 1')
    return {'id':id, 're':re}

并用(在'if name'块中)调用它:

args = parser.parse_args()
print(function_1(args.id, args.re))

结果是这样的

1659:~/mypy$ python3 stack37557027_A.py 
function 1
{'re': 'C', 'id': 'A'}

脚本 B 也可以生成该字典的字符串显示

1659:~/mypy$ python3 stack37557027_B.py
b"function 1\n{'re': 'C', 'id': 'A'}\n"

现在如果在 B 我愿意

import stack37557027_A as A
print(A.function_1('AA','BB'))

我明白了

{'id': 'AA', 're': 'BB'}

因此,如果所有操作都是 A 的主体,并且 if __name__ 块就像 argparse 解析和委托一样,我可以通过导入使用来自 A 的函数,并取回字典(或其他任何内容)对象这些函数产生)。换句话说,我不需要将A 作为子进程或系统进程调用。

如果您确实需要将A 作为一个单独的进程运行,并且仍要返回Python 对象,我认为您可以使用multiprocessing

https://docs.python.org/2/library/multiprocessing.html#exchanging-objects-between-processes

https://pymotw.com/2/multiprocessing/basics.html

【讨论】:

    【解决方案3】:

    版本 3 几乎是正确的。尽管您的示例中缺少很多 '",但我不确定您的代码是否对您有用...

    from subprocess import call
    
    # you need pass the name + all the arguments as a vector here 
    process = call(["script_A.py", "-i", "A", "-r", "C"])
    
    #Other stuff that script B does
    

    如果要捕获输出,最好使用Popen 而不是call

    from subprocess import call, Popen
    
    # you need pass the name + all the arguments as a vector here 
    process = Popen(["script_A.py", "-i", "A", "-r", "C"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
    
    output = process.communicate()  # let it run until finished
    
    print output[0]  # stdout
    print output[1]  # stderr
    #Other stuff that script B does
    

    【讨论】:

    • 我在实现这一点时遇到了一些麻烦。我已经更新了我所做的以显示我得到了什么。感谢您的帮助,非常感谢。
    • @python_rookie 您的 1 没有将参数作为列表传递。号码 2 正在尝试呼叫 script_A 而不是 script_A.py。请多加注意。确保script_A.py 在您的路径中,否则您必须将完整路径传递给它。
    猜你喜欢
    • 2017-06-16
    • 2016-07-30
    • 2020-06-19
    • 2021-10-09
    • 2018-07-15
    • 2013-07-30
    • 2011-06-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多