2016-07-26 469 views
1

我想寫一個Python代碼與使用命令行提示的另一個軟件進行交互。執行命令行提示後,目錄中會生成多個輸出文件,並且軟件會使用這些輸出文件進行一些計算。另外,我的程序的其餘部分使用這些輸出文件。目前,我跑我的Python代碼,然後在命令行提示符手動輸入,然後但調用我的代碼的休息和工作正常,當我試圖把:subprocess.call()或subprocess.Popen生成/使用輸出文件

subprocess.call(['sfit4Layer0.py', '-bv5', '-fs'], shell=False) 

到我的文件,它不正確執行(不生成輸出文件)。

當我做出上述代碼時,它是自己的個人python代碼,並在我的代碼的第一部分後立即調用它 - 它也工作。

根據我的輸出,我確信問題是這樣的:調用生成多個文件,然後使用這些文件進行計算,但是,它沒有生成正確的文件,因此我的輸出中出現錯誤。所以在某種程度上,它似乎超越了自己:在計算之前不等待輸出文件被生成,但是當我在程序之外單獨運行此命令時,它仍然有效。任何想法爲什麼會發生?

我在做什麼錯?我是否需要指定目錄(輸出文件是否可以放在我的電腦的其他地方)?我需要使用subprocess.Popen嗎?我搜索了互聯網,但我是Python新手(ish),並且徹底難倒了。

歡迎任何建議。謝謝!

編輯:對於那些誰問,這裏是sfit4Layer0.py代碼:

#! /usr/bin/python 
##! /usr/local/python-2.7/bin/python 
##! /usr/bin/python 
##! /usr/bin/python 
# Change the above line to point to the location of your python executable 
#---------------------------------------------------------------------------------------- 
# Name: 
#  sfit4Layer0.py 
# 
# Purpose: 
#  This file is the zeroth order running of sfit4. It accomplishes the following: 
#   1) Calls pspec to convert binary spectra file (bnr) to ascii (t15asc) 
#   2) Calls hbin to gather line parameters from hitran 
#   3) Calls sfit4 
#   4) Calls error analysis from Layer1mods.py 
#   5) Clean outputs from sfit4 call 
# 
# 
# External Subprocess Calls: 
#   1) pspec executable file from pspec.f90 
#   2) hbin executable file from hbin.f90 
#   3) sfit4 executable file from sfit4.f90 
#      4) errAnalysis from Layer1mods.py 
# 
# 
# 
# Notes: 
# 1) Options include: 
#   -i <dir>  : Optional. Data directory. Default is current working directory 
#   -b  <dir/str> : Optional. Binary directory. Default is hard-code. 
#   -f <str>  : Run flags, h = hbin, p = pspec, s = sfit4, e = error analysis, c = clean 
# 
# 
# Usage: 
#  ./sfit4Layer0.py [options] 
# 
# 
# Examples: 
#  1) This example runs hbin, pspec, sfit4, error analys, and cleans working directory prior to execution 
#   ./sfit4Layer0.py -f hpsec 
# 
#  2) This example just runs sfit4 
#   ./sfit4Layer0.py -f s 
# 
#  3) This example cleans the output file created by sfit4 in directory (/User/home/datafiles/) which is not the current directory 
#   ./sfit4Layer0.py -i /User/home/datafiles/ -f c 
# 
# Version History: 
#  Created, May, 2013 Eric Nussbaumer ([email protected]) 
# 
# 
# License: 
# Copyright (c) 2013-2014 NDACC/IRWG 
# This file is part of sfit4. 
# 
# sfit4 is free software: you can redistribute it and/or modify 
# it under the terms of the GNU General Public License as published by 
# the Free Software Foundation, either version 3 of the License, or 
# any later version. 
# 
# sfit4 is distributed in the hope that it will be useful, 
# but WITHOUT ANY WARRANTY; without even the implied warranty of 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
# GNU General Public License for more details. 
# 
# You should have received a copy of the GNU General Public License 
# along with sfit4. If not, see <http://www.gnu.org/licenses/> 
# 
#---------------------------------------------------------------------------------------- 


#--------------- 
# Import modules 
#--------------- 
import sys 
import os 
import getopt 
import sfitClasses as sc 
from Layer1Mods import errAnalysis 
from Tkinter import Tk 
from tkFileDialog import askopenfilename 


#------------------------ 
# Define helper functions 
#------------------------ 
def usage(binDirVer): 
     print 'sfit4Layer0.py -f <str> [-i <dir> [-b <dir/str> ] \n' 
     print '-i <dir>  Data directory. Optional: default is current working directory' 
     print '-f <str>  Run Flags: Necessary: h = hbin, p = pspec, s = sfit4, e = error analysis, c = clean' 
     print '-b <dir/str> Binary sfit directory. Optional: default is hard-coded in main(). Also accepts v1, v2, etc.' 
     for ver in binDirVer: 
       print '    {}: {}'.format(ver,binDirVer[ver])   

     sys.exit() 


def main(argv): 

     #---------------- 
     # Initializations 
     #---------------- 
     #------------ 
     # Directories 
     #------------ 
     wrkDir = os.getcwd()        # Set current directory as the data directory 
     binDir = '/data/bin'        # Default binary directory. Used of nothing is specified on command line 
     binDirVer = { 
     'v1': '/data/ebaumer/Code/sfit-core-code/src/', # Version 1 for binary directory (Eric) 
     'v2': '/data/tools/400/sfit-core/src/',    # Version 2 for binary directory (Jim) 
     'v3': '/Users/jamesw/FDP/sfit/400/sfit-core/src/',    # Version 2 for binary directory (Jim) 
     'v4': '/home/ebaumer/Code/sfit4/src/', 
     'v5': '/Users/allisondavis/Documents/Summer2016/sfit4_0.9.4.3/src' 
     } 


     #---------- 
     # Run flags 
     #---------- 
     hbinFlg = False           # Flag to run hbin 
     pspecFlg = False           # Flag to run pspec 
     sfitFlg = False           # Flag to run sfit4 
     errFlg = False           # Flag to run error analysis 
     clnFlg = False           # Flag to clean directory of output files listed in ctl file 

     #-------------------------------- 
     # Retrieve command line arguments 
     #-------------------------------- 
     try: 
       opts, args = getopt.getopt(sys.argv[1:], 'i:b:f:?') 

     except getopt.GetoptError as err: 
       print str(err) 
       usage(binDirVer) 
       sys.exit() 

     #----------------------------- 
     # Parse command line arguments 
     #----------------------------- 
     for opt, arg in opts: 
       # Data directory 
       if opt == '-i': 
         wrkDir = arg 
         sc.ckDir(wrkDir,exitFlg=True) 

       # Binary directory 
       elif opt == '-b': 
         if not sc.ckDir(arg,exitFlg=False,quietFlg=True): 
           try:    binDir = binDirVer[arg.lower()] 
           except KeyError: print '{} not a recognized version for -b option'.format(arg); sys.exit() 

         else: binDir = arg 

         if not(binDir.endswith('/')): binDir = binDir + '/' 

       # Run flags 
       elif opt == '-f': 
         flgs = list(arg) 
         for f in flgs: 
           if f.lower() == 'h': hbinFlg = True 
           elif f.lower() == 'p': pspecFlg = True 
           elif f.lower() == 's': sfitFlg = True 
           elif f.lower() == 'e': errFlg = True 
           elif f.lower() == 'c': clnFile = True 
           else: print '{} not an option for -f ... ignored'.format(f) 
       elif opt == '-?': 
         usage(binDirVer) 
         sys.exit()       

       else: 
         print 'Unhandled option: {}'.format(opt) 
         sys.exit() 

     #-------------------------------------- 
     # If necessary change working directory 
     # to directory with input data. 
     #-------------------------------------- 
     if os.path.abspath(wrkDir) != os.getcwd(): os.chdir(wrkDir) 
     if not(wrkDir.endswith('/')): wrkDir = wrkDir + '/' 

     #-------------------------- 
     # Initialize sfit ctl class 
     #-------------------------- 
     ctlFileName = wrkDir + 'sfit4.ctl' 
     if sc.ckFile(wrkDir+'sfit4.ctl'): ctlFileName = wrkDir + 'sfit4.ctl' 
     else: 
       Tk().withdraw() 
       ctlFileName = askopenfilename(initialdir=wrkDir,message='Please select sfit ctl file') 

     ctlFile = sc.CtlInputFile(ctlFileName) 
     ctlFile.getInputs() 

     #------------------------ 
     # Initialize sb ctl class 
     #------------------------ 
     if errFlg: 
       if sc.ckFile(wrkDir+'sb.ctl'): sbCtlFileName = wrkDir + 'sb.ctl' 
       else: 
         TK().withdraw() 
         sbCtlFileName = askopenfilename(initialdir=wrkDir,message='Please select sb ctl file') 

       sbCtlFile = sc.CtlInputFile(sbCtlFileName) 
       sbCtlFile.getInputs() 

     #--------------------------- 
     # Clean up output from sfit4 
     #--------------------------- 
     if clnFlg: 
       for k in ctlFile.inputs['file.out']: 
         if 'file.out' in k: 
           try:   os.remove(wrkDir + ctlFile.inputs[k]) 
           except OSError: pass 

     #---------- 
     # Run pspec 
     #---------- 
     if pspecFlg: 
       print '*************' 
       print 'Running pspec' 
       print '*************' 
       rtn = sc.subProcRun([binDir + 'pspec']) 

     #---------- 
     # Run hbin 
     #---------- 
     if hbinFlg: 
       print '************' 
       print 'Running hbin' 
       print '************' 
       rtn = sc.subProcRun([binDir + 'hbin']) 

     #---------- 
     # Run sfit4 
     #---------- 
     if sfitFlg: 
       print '************' 
       print 'Running sfit' 
       print '************' 
       rtn = sc.subProcRun([binDir + 'sfit4']) 

     #------------------- 
     # Run error analysis 
     #------------------- 
     if errFlg: 
       print '**********************' 
       print 'Running error analysis' 
       print '**********************' 
       rtn = errAnalysis(ctlFile,sbCtlFile,wrkDir) 



if __name__ == "__main__": 
     main(sys.argv[1:]) 
+0

你有沒有檢查是否有如果程序在同一時間運行時仍然在另一個程序中打開,那麼程序不會嘗試打開該文件? – lu1her

+0

我該如何檢查?或讓它做到這一點?這是我認爲可能是問題 – alli

+0

它取決於你的程序的行爲,如果他們只是使用文件一次確保'file.close()'之前打開它在一個不同的程序,但如果你必須檢查在不同的程序中同樣的文件我建議你使用共享內存技術 – lu1her

回答

0

試試這個:subprocess.call('sfit4Layer0.py -bv5 -fs', shell=True)

+0

仍然無法正常工作...... – alli

0

如果你正試圖從你的Python腳本中調用另一個Python腳本的subprocess.call()方法適合您的操作。

我建議你把

subprocess.call(['sfit4Layer0.py', '-bv5', '-fs'], shell=True) 

希望這個解決方案工作。

當您想要將STDIN/STDOUT或STDERR從一個進程傳送到另一個進程時,通常會使用Popen。

此外,當您編寫文件時,請確保您創建文件或目錄路徑爲絕對路徑,這將幫助您將文件始終放置在所需位置。

快樂編碼。

0
subprocess.call(['sfit4Layer0.py', '-bv5', '-fs'], shell=False) 
  1. 假定sfit4Layer0.py是可執行的,它可能不是
  2. 假設sfit4Layer0.py包含#!的/ usr/bin中/ Python的家當,這也可能不是。

如果腳本確實含有家當和不可執行 嘗試:

subprocess.call(['python','/path/to/script/sfit4Layer0.py','-bv5','-fs'], shell=False) 

如果腳本是可執行的,並且包含家當 嘗試:

subprocess.call(['/path/to/script/sfit4Layer0.py -bv5 -fs'], shell=True) 
+0

這些都沒有工作:/根據我的輸出,我相信,問題是這樣的:調用生成多個文件,然後使用這些文件進行計算,但是,它不生成正確的文件,所以我在我的輸出中得到錯誤。所以在某種程度上,它似乎超越了自己:在計算之前不等待輸出文件被生成,但是當我在程序之外單獨運行此命令時,它仍然有效。任何想法爲什麼會發生? – alli

+0

在這種情況下,請使用Popen()。不用在被調用的腳本中看到代碼,就很難說。請參閱:http://stackoverflow.com/questions/15107714/wait-process-untill-all-subprocess-finish –

+0

您是否嘗試過打印調試代碼來觀察被調用腳本中正在發生的進度。打印是一個調試工具的地獄。 –