2016-05-30 57 views
0
運行腳本使用多個參數

我的問題是有關這個問題早 - Python subprocess usagePython腳本:使用子

我試圖使用python

nccopy -k 4「http://www.esrl.noaa.gov/psd/thredds/dodsC/Datasets/ncep.reanalysis2/pressure/air.2014.nc?air[408:603][2][20:34][26:40]」富來運行這個命令.nc

當我運行上述命令時,我應該能夠在我的磁盤上看到名爲foo.nc的文件或網絡錯誤,指出無法訪問該URL或未找到遠程URL。

目前ESRL NOAA服務器宕機 - 所以當我運行上面的命令,我得到

語法錯誤,意想不到的$結束,預計SCAN_ATTR或SCAN_DATASET或SCAN_ERROR 背景:^ 的NetCDF:訪問故障 地點:文件nccopy.c;線1348

我應該得到同樣的錯誤,當我運行python腳本

這是我的代碼,我無法弄清楚到底如何進一步進行 -

我試圖分裂「 -k 4" 成兩個參數並刪除引號,我仍然得到這個錯誤nccopy:無效的格式:4個

打印(sys.argv中)data.py

[ 'data.py' 的結果,「 -k','4','http://www.esrl.noaa.gov/psd/thredds/dodsC/Datasets/ncep.reanalysis2/pressure/air.2014.nc?air[480:603][20:34][26:40]','foo.nc']

import numpy as np 

import subprocess 

import sys 

url = '"http://www.esrl.noaa.gov/psd/thredds/dodsC/Datasets/ncep.reanalysis2/pressure/air.2014.nc?air[408:603][2][20:34][26:40]"' 

outputFile = 'foo.nc' 

arg1 = "-k 4" 

arg3 = url 

arg4 = outputFile 


print (input) 

subprocess.check_call(["nccopy",arg1,arg3,arg4]) 
+0

首先,請使用[shlex](https://docs.python.org/3/library/shlex.html),如果可能,請使用'Popen()'而不是'check_call()'。另外你的問題是你不分開'-k'和'4'。子進程自動嘗試爲每個參數元素插入一個空格。嘗試使用'[「nccopy」,'-k','4']' – Torxed

+0

當調用系統命令時,傳統的shell邏輯仍然適用,意味着'''可以解析變量和字符,而'''不包含參數除非你想解析參數,否則我會用'''來包裝參數。 – Torxed

回答

2

有這裏有兩個難題。
一個是該子進程處理您的參數並嘗試使用4作爲單獨的參數。

另一個是系統調用仍在正常的shell規則下,這意味着參數和命令將被解析爲metacharacters aka特殊字符。在這種情況下,您正在包裝[]

有你需要將每個參數分開,它的價值將在參數列表不同的對象,例如-k 4應該是['-k', '4'],你需要來包裝'...',而不是"..."參數/值。

試試這個,shlex.split()做繁重的工作適合你,和我換周圍的URL封裝字符:

import numpy as np 
import subprocess 
import sys 
import shlex 

url = "'http://www.esrl.noaa.gov/psd/thredds/dodsC/Datasets/ncep.reanalysis2/pressure/air.2014.nc?air[408:603][2][20:34][26:40]'" 

outputFile = 'foo.nc' 
command_list = shlex.split('nccopy -k 4 ' + url + ' ' + outpufFile) 

print(command_list) 

subprocess.check_call(command_list) 
+2

如果'outputFile'中有一個空格,你的代碼示例失敗。沒有理由在這裏使用'shlex.split()'([它可以在一般情況下被愚弄])(http://stackoverflow.com/questions/14386775/subprocess-call/14386815#comment45736245_14386815))。在REPL中使用'shlex.split()'(從shell命令創建種子參數列表,以後可以手動進行微調) - 在最終的代碼中避免它。 – jfs

+0

@JFSebastian - 你能寫一個與其他兩個完全不同的替代答案? – gansub

2

代替arg1 =「-k 4」,改用兩個參數。

import subprocess 


url = 'http://www.esrl.noaa.gov/psd/thredds/dodsC/Datasets/ncep.reanalysis2/pressure/air.2014.nc?air[408:603][2][20:34][26:40]' 

outputFile = 'foo.nc' 

arg1 = "-k" 
arg2 = "4" 
arg3 = url 
arg4 = outputFile 

subprocess.check_call(["nccopy", arg1, arg2, arg3, arg4]) 

也看到這裏Python subprocess arguments

+0

是的,我會編輯 – SnoozeTime

1

如果您有多個參數運行單個節目的工作shell命令,你想要參數化它,例如,要使用變量文件名而不是硬編碼值,則可以使用shlex.split()創建一個命令行參數列表,您可以將該列表傳遞給subprocess模塊並用變量替換所需的參數,例如:

>>> shell_command = "python -c 'import sys; print(sys.argv)' 1 't w o'" 
>>> import shlex 
>>> shlex.split(shell_command) 
['python', '-c', 'import sys; print(sys.argv)', '1', 't w o'] 

要使用相同的Python解釋器作爲父腳本運行的命令,sys.executable可以使用,我們可以通過的variable代替'1'一個:

#!/usr/bin/env python 
import random 
import sys 
import subprocess 

variable = random.choice('ab') 
subprocess.check_call([sys.executable, '-c', 'import sys; print(sys.argv)', 
         variable, 't w o']) 

注:

  • 每個列表項的一個命令行參數
  • shlex.split()中的翅人代碼
  • 裏面有't w o'即無報價,'t w o'來代替'"t w o"'"'t w o'"

subprocess模塊不運行在默認情況下的殼,因此你不需要逃避shell元字符,作爲命令行參數中的空格。反之,如果你的命令使用了一些shell功能(例如文件模式),那麼要麼在Python中重新實現相應的功能(例如,使用glob模塊),要麼使用shell=True並按原樣按字符串傳遞命令。在這種情況下,您可能需要pipes.quote()來轉義可變參數。 Wildcard not working in subprocess call using shlex