Подпроцесс работает / вызов не работает - PullRequest
0 голосов
/ 27 июня 2018

Я хочу использовать утилиту " raster2pgsql " в моем коде Python. Когда я использую его в терминале Linux, он работает нормально. Это команда:

$ raster2pgsql -a "/mnt/c/Users/Jan/path/to/raster/dem.tiff" test_schema.raster2 | psql -h localhost -d pisl -U pisl

Затем я использую subprocess.run (я также пробовал subprocess.call), чтобы использовать этот же инструмент в моем коде Python. Это мой код:

from subprocess import run
command = ["raster2pgsql", "-a", '"' + file_name + '"', self.schema_name +  "." + identifier, "|", "psql", "-h", "localhost", "-p", "5432", "-d", self.dbname]
run(command)

Я получаю эту ошибку:

ERROR: Unable to read raster file: "/mnt/c/Users/Jan/path/to/raster/dem.tiff"

Печать command дает то, что я считаю правильным (эквивалентно тому, что работало в терминале):

['raster2pgsql', '-a', '"/mnt/c/Users/Jan/path/to/raster/dem.tiff"', 'test_schema.raster2', '|', 'psql', '-h', 'localhost', '-p', '5432', '-d', 'pisl']

Я дважды проверил, что путь к растровому файлу правильный, пробовал одинарные, двойные кавычки, но ничего не помогает. Я рассмотрел ряд похожих вопросов ( здесь , здесь или здесь ), но не нашел ничего полезного.

Я использую Python 3.5 и Linux Bash Shell в Windows 10.

Вопрос : Что плохого в том, как я использую подпроцесс?

1 Ответ

0 голосов
/ 27 июня 2018

2 номера здесь:

  • не нужно дополнительно указывать имя файла. Он передается в систему буквально, и, поскольку нет файла с именем "/tmp/something", команда не выполняется.
  • секунда, чтобы пройти трубу, нужно shell=True

так быстро:

command = ["raster2pgsql", "-a", file_name, self.schema_name +  "." + identifier, "|", "psql", "-h", "localhost", "-p", "5432", "-d", self.dbname]
run(command,shell=True)

или с помощью командной строки (потому что shell=True требователен к списку аргументов):

command = "raster2pgsql -a "+ file_name + " " + self.schema_name +  "." + identifier + " | psql -h localhost -p 5432 -d" + self.dbname
run(command,shell=True)

(некрасиво, не правда ли?)

намного лучше запускать 2 процесса без shell=True и передавать их вместе, используя python, более переносимо и безопасно (не знаю, как shell=True реагирует со списком аргументов в Linux):

from subprocess import *
command1 = ["raster2pgsql", "-a", file_name, self.schema_name +  "." + identifier]
p = Popen(command1,stdout=PIPE)
command2 = ["psql", "-h", "localhost", "-p", "5432", "-d", self.dbname]
run(command2,stdin=p.stdout)

Первый созданный объект Popen записывает свой вывод в канал (благодаря аргументу stdout=PIPE). Функция run также может принимать входные данные в виде канала (благодаря stdin=p.stout). Она потребляет выходные данные первой команды, создавая цепочку собственных команд по конвейеру без необходимости использования оболочки (и предостережений при цитировании, пробелы, специальные интерпретации символов и тому подобное ...)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...