2016-05-31 90 views
3

我有一個script_A,它使用argparser來處理不同的輸入,我使用它來執行一個函數。我現在需要腳本B來調用腳本A,並從內部運行所有腳本A(它處理不同的輸入)。我正在使用Windows。Python:運行腳本處理腳本內的argparser B

目標: 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) 

一個腳本運行正常,當我使用它它的工作。我使用命令行參數來提交輸入,必需的,有時是可選的。

這是腳本B,我已經試過如下:

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 

import sys 
import os 
import script_A 

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

#Other stuff that script B does 

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的初學者。

我曾嘗試以下基於評論:

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

類型錯誤:__init_()得到了關鍵字參數 '標準輸出'

我嘗試添加多個值自我論證,但我得到以下錯誤

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

類型錯誤:__init_()得到了關鍵字參數 'stderr的' 多個值

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

raise ch ild_exception

我不知道這是什麼意思。

+4

爲什麼你需要通過命令行來傳遞參數?只需'輸入'並直接調用函數*。 – jonrsharpe

+0

對不起,您能詳細解釋一下嗎?只是爲了澄清我不需要在腳本B中運行腳本A中的單獨函數。我需要運行整個事情。我還希望能夠靈活地分析參數,以便在我想顯示更多輸出時與不輸出時相比。 –

+0

那麼這些替代方法做了什麼(或不做)?你期望發生什麼?如果你不直接使用它的函數(如'os.system'版本),則不需要'import script_A'。 – hpaulj

回答

1
p = subprocess.Popen("your_a_code_with_args_here", 
        shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) 

(stdoutput, erroutput) = p.communicate() 

然後你的B代碼可以根據A代碼的輸出做事情。

+0

非常感謝您的建議。我試過了,它不起作用。我有一些麻煩。我已經更新了我的問題描述,以反映我現在看到的內容。我想傳遞整個腳本運行後製作的字典。 –

+0

不知道如何用管道交換python對象。也許你不能只返回python對象,使用json.dumps來編碼你的對象並返回;而你的B代碼可以使用json.loads來解碼json字符串並從代碼A中獲得真正的python對象。 – lagom

0

版本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 
+0

我在實現這個時遇到了一些麻煩。我已經更新了我所做的工作來展示我所得到的。感謝您的幫助,非常感謝。 –

+0

@python_rookie您的** 1 **不會將參數作爲列表傳遞。數字** 2 **試圖調用'script_A'而不是'script_A.py'。請多加關注。確保'script_A.py'在你的路徑中,否則你必須通過它的完整路徑。 – RedX

1

我已經凝結的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確實是具有導入的2個功能,其可運行,從乙

stack375570237_A.function_A() 

如果不清楚,重新閱讀關於if __name__ == "__main__":的目的文檔以及運行腳本和i之間的區別導入一個模塊。這是重要的基本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/

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

你更新的目標是:

, I need to run script_A and then pass one of the dictionaries, dictionary D, that is calculated (output from A) to be passed on to B. T

與此的一個問題是,這些方法到目前爲止使用或者只顯示一個字符串到標準輸出,或者返回一個字符串給調用者(從標準輸出)。它們不像字典那樣返回Python對象。

你的A這個字典是在哪裏生產的?它如何取決於​​選項?

允許變化的,以便在所述主體中的功能產生的詞典

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

並用稱之爲(在「如果」塊):

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" 

現在如果在BI做

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