在Python中调用bash命令会返回错误,但在终端中工作

时间:2017-01-03 20:07:08

标签: python bash

以下是与我相关的代码:

def grd_commands(directory):
    for filename in os.listdir(directory)[1:]:
        print filename
        new_filename = ''
        first_letter = ''
        second_letter = ''
        bash_command = 'gmt grdinfo ' + filename + ' -I-'
        print bash_command
        coordinates = Popen(bash_command, stdout=PIPE, shell=True)
        coordinates = coordinates.communicate()
        latlong = re.findall(r'^\D*?([-+]?\d+)\D*?[-+]?\d+\D*?([-+]?\d+)', coordinates)
        if '-' in latlong[1]:
            first_letter = 'S'
        else:
            first_letter = 'N'
        if '-' in latlong[0]:
            second_letter = 'W'
        else:
            second_letter = 'E'

        new_filename = first_letter + str(latlong[1]) + second_letter + str(latlong[0]) + '.grd'
        Popen('gmt grdconvert ' + str(filename) + ' ' + new_filename, shell=True)

filename是传递给函数的文件的名称。当我运行我的代码时,我收到此错误:

/bin/sh: gmt: command not found
Traceback (most recent call last):
  File "/Users/student/Desktop/Code/grd_commands.py", line 38, in <module>
    main()
  File "/Users/student/Desktop/Code/grd_commands.py", line 10, in main
    grd_commands(directory)
  File "/Users/student/Desktop/Code/grd_commands.py", line 23, in grd_commands
    latlong = re.findall(r'^\D*?([-+]?\d+)\D*?[-+]?\d+\D*?([-+]?\d+)', coordinates).split('\n')
  File "/System/Library/Frameworks/Python.framework/Versions/2.6/lib/python2.6/re.py", line 177, in findall
    return _compile(pattern, flags).findall(string)
TypeError: expected string or buffer

如果我打印出字符串bash_command并尝试将其输入终端,则它将完全起作用。为什么在我的Python脚本调用时它不起作用?

2 个答案:

答案 0 :(得分:2)

整个命令行被视为单个命令 name 。您需要使用shell=True让shell将其解析为命令行:

coordinates = Popen(bash_command, stdout=PIPE, shell=True)

或最好将命令名及其参数存储为列表的单独元素:

bash_command = ['gmt', 'grdinfo', filename, '-I-']
coordinates = Popen(bash_command, stdout=PIPE)

答案 1 :(得分:0)

Popen列出了一系列参数。使用shell = True

时会出现警告

如果与不受信任的输入相结合,传递shell = True可能会造成安全隐患。

试试这个:

from subprocess import Popen, PIPE
bash_command = 'gmt grdinfo ' + filename + ' -I-'
print(bash_command)
coordinates = Popen(bash_command.split(), stdout=PIPE)
print(coordinates.communicate()[0])

确保gmt安装在/ etc / environment文件中由PATH指定的位置:

PATH=$PATH:/path/to/gmt

或者,在bash_command中指定gmt的路径:

bash_command = '/path/to/gmt grdinfo ' + filename + ' -I-'

您应该能够找到路径:

which gmt

正如其他人所建议的那样,实际列表是最好的方法,而不是字符串。此外,您必须使用&#39; \&#39;如果文件中有空格,则实际访问该文件。

for filename in os.listdir(directory)[1:]:
    bash_command = ['gmt', 'grdinfo', filename.replace(" ", "\ "), '-I-']