Python 脚本 : 运行 使用子进程的具有多个参数的脚本

Python script : Running a script with multiple arguments using subprocess

我的问题与之前的问题有关 - Python subprocess usage

我正在尝试 运行 使用此命令 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]" foo.nc

当我 运行 上面的命令时,我应该能够在我的磁盘上看到一个名为 foo.nc 的文件,或者网络错误表明无法访问 URL 或远程 URL 未找到。

目前 ESRL NOAA 服务器已关闭 - 所以当我 运行 上述命令时,我得到

语法错误,意外的 $end,应为 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])

使用两个参数代替 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

这里有两个难题。
一个是子进程处理您的参数并尝试使用 4 作为单独的参数。

另一个是系统调用仍然遵循正常的 shell 规则,这意味着参数和命令将被解析为 metacharacters 也就是特殊字符。在这种情况下,您包装了 [].

你需要将每个参数和它的值分开到参数列表中的单独对象中,例如 -k 4 应该是 ['-k', '4'] 并且你需要将 parameters/values 包装在'...' 而不是 "...".

试试这个,shlex.split() 为你做 grunt 工作,我交换了 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)

如果您有一个有效的 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 元字符,例如 space 在命令行参数中。相反,如果您的命令使用某些 shell 功能(例如,文件模式),则要么在 Python 中重新实现相应的功能(例如,使用 glob 模块),要么使用 shell=True 并按原样将命令作为字符串传递。在这种情况下,您可能需要 pipes.quote() 来转义变量参数。 Wildcard not working in subprocess call using shlex