Команда работает в оболочке, но не в подпроцессе - PullRequest
1 голос
/ 08 марта 2019

Я пытаюсь запустить команду, используя пакет python subprocess. Я добавил путь к скомпилированному исполняемому файлу к своему PATH на машине с Ubuntu.

Когда я делаю это, это работает :

myexecutable input_file output_file

Когда я делаю это, это работает :

import subprocess
import shlex

cmd = '/path/to/my/myexecutable input_file output_file'
subprocess.Popen(shlex.split(cmd))

Вот кикер. Когда я делаю это, не работает :

import subprocess
import shlex

cmd = 'myexecutable input_file output_file'
subprocess.Popen(shlex.split(cmd))

Это дает мне:

OSError                                   Traceback (most recent call last)
<ipython-input-4-8f5c3da8b0a3> in <module>()
----> 1 subprocess.call(shlex.split(cmd))

/home/me/miniconda3/envs/mypy2/lib/python2.7/subprocess.pyc in call(*popenargs, **kwargs)
    170     retcode = call(["ls", "-l"])
    171     """
--> 172     return Popen(*popenargs, **kwargs).wait()
    173
    174

/home/me/miniconda3/envs/mypy2/lib/python2.7/subprocess.pyc in __init__(self, args, bufsize, executable, stdin, stdout, stderr, preexec_fn, close_fds, shell, cwd, env, universal_newlines, startupinfo, creationflags)
    392                                 p2cread, p2cwrite,
    393                                 c2pread, c2pwrite,
--> 394                                 errread, errwrite)
    395         except Exception:
    396             # Preserve original exception in case os.close raises.

/home/me/miniconda3/envs/mypy2/lib/python2.7/subprocess.pyc in _execute_child(self, args, executable, preexec_fn, close_fds, cwd, env, universal_newlines, startupinfo, creationflags, shell, to_close, p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite)
   1045                         raise
   1046                 child_exception = pickle.loads(data)
-> 1047                 raise child_exception
   1048
   1049

OSError: [Errno 2] No such file or directory

Что дает?

1 Ответ

1 голос
/ 09 марта 2019

Какая бы оболочка вы не использовали (кроме subprocess.Popen(..., shell=True), но с оговорками), вычисляется фактический исполняемый файл на основе переменной окружения PATH.

subprocess.Popen() само по себе не. Один из популярных способов обойти это (т.е. выполнить поиск пути) в системах UNIX - использовать широко доступный инструмент /usr/bin/env, который выполняет то же расширение, т.е.

subprocess.Popen(['/usr/bin/env', 'mytool', 'hurr', 'durr'])

но это не переносимо для Windows.

Лучший способ решить эту проблему - выполнить поиск самостоятельно, то есть выяснить полный путь к исполняемому файлу и передать его subprocess.Popen() - os.path.realpath() может быть вашим другом здесь.

...