Python subprocess.call () не работающий как ожидалось

Я запустил вниз эту кроличью нору как средство ознакомиться с тем, как можно было бы пойти о создании сценария установки в Python. Выбор Python был просто базирован в моем знакомстве с ним, в то время как я уверен, что были бы лучшие альтернативы, чем Python для этой задачи.

Цель этого сценария состояла в том, чтобы установить ROS на машину, запускающую скрипт, и также установить среду сережки. Направления могут быть найдены здесь и здесь, соответственно.

Сценарий, поскольку это в настоящее время находится, следующие:

subprocess.call(["sudo", "sh", "-c", "'echo \"deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main\" > /etc/apt/sources.list.d/ros-latest.list'"])
subprocess.call(["sudo", "apt-key", "adv", "--keyserver", "hkp://ha.pool.sks-keyserver.net:80", "--recv-key", "0xB01FA116"])
subprocess.call(["sudo", "apt-get", "update"])
subprocess.call(["sudo", "apt-get", "install", "ros-kinetic-desktop-full", "-y"])
subprocess.call(["sudo", "rosdep", "init"])
subprocess.call(["rosdep", "update"])
subprocess.call(["echo", '"source /opt/ros/kinetic/setup.bash"', ">>", "~/.bashrc", "source", "~/.bashrc"])
subprocess.call(["sudo", "apt-get", "install", "python-rosinstall", "-y"])
mkdir_p(os.path.expanduser('~') + "/catkin_ws/src")
subprocess.call(["(cd "+ os.path.expanduser('~') + "/catkin_ws/src)"])
subprocess.call(["(cd "+ os.path.expanduser('~') + "/catkin_ws && catkin_make)"])
subprocess.call(["(cd "+ os.path.expanduser('~') + "/catkin_ws && source devel/setup.bash"])

Когда сценарий в настоящее время является выполнениями это ошибки с ошибкой:

Traceback (most recent call last):
  File "setup.py", line 46, in <module>
    subprocess.call(["(cd "+ os.path.expanduser('~') + "/catkin_ws/src)"])
  File "/usr/lib/python2.7/subprocess.py", line 523, in call
    return Popen(*popenargs, **kwargs).wait()
  File "/usr/lib/python2.7/subprocess.py", line 711, in __init__
    errread, errwrite)
  File "/usr/lib/python2.7/subprocess.py", line 1343, in _execute_child
    raise child_exception
OSError: [Errno 2] No such file or directory

Я проверил, что команда действительно правильно работает, когда вручную выполняется из окна терминала, и как таковой, я полагаю, что это - фундаментальное недоразумение о том, как этот сценарий и его объем обрабатываются в ОС. Часть, которая вызывает меня много беспорядка, - то, почему это жалуется, что не может определить местоположение предоставленного каталога, в то время как я проверил, что этот каталог существует. Когда команда скорее печатается из Python и вставляется в окно терминала, ни с какими ошибками не встречаются.

10
задан 22 July 2016 в 01:49

4 ответа

Значением по умолчанию subprocess.call не использует оболочку для выполнения наших команд, Вы так не можете окружить команды как cd.

Для использования оболочки для выполнения использования команд shell=True как параметр. В этом случае рекомендуется передать Ваши команды как единственную строку, а не как список. И поскольку это выполняется оболочкой, можно использовать ~/ в пути, также:

subprocess.call("(cd ~/catkin_ws/src && catkin_make)", shell=True)
17
ответ дан 23 November 2019 в 04:19

subprocess.call() ожидает список, с первым объектом, очевидно, являющимся законной командой оболочки. Сравните это, например:

>>> subprocess.call(['echo hello'])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.7/subprocess.py", line 523, in call
    return Popen(*popenargs, **kwargs).wait()
  File "/usr/lib/python2.7/subprocess.py", line 711, in __init__
    errread, errwrite)
  File "/usr/lib/python2.7/subprocess.py", line 1343, in _execute_child
    raise child_exception
OSError: [Errno 2] No such file or directory
>>> subprocess.call(['echo', 'hello'])
hello
0

В Вашем случае, subprocess.call(["(cd "+ os.path.expanduser('~') + "/catkin_ws/src)"]) будет ожидать находить двоичный файл, который похож так (отметьте обратную косую черту, определяющую символ пространства):

 cd\ /home/user/catkin_ws/src

, Который рассматривают как одно единственное имя, которое, как должны ожидать, будет жить где-нибудь на Вашей системе. То, что Вы действительно хотели бы сделать:

 subprocess.call(["cd", os.path.expanduser('~') + "/catkin_ws/src"])

Примечание, что я удалил круглую скобку вокруг запятой, как нет никакой причины использовать подоболочку.

РЕДАКТИРОВАНИЕ :

, Но это было уже упомянуто progo в комментариях, что использование cd в этом случае избыточно. Ответ Florian также правильно упоминает, что subprocess.call() не использует оболочку. Вы могли приблизиться к этому двумя способами. Один, Вы могли использовать subprocess.call("command string",shell=True)

другой путь, должен назвать определенную оболочку явно. Это особенно полезно, если Вы хотите запустить скрипт, который требует определенной оболочки. Таким образом Вы могли сделать:

subprocess.call(['bash' , os.path.expanduser('~')  + "/catkin_ws/src"  ) ] )
5
ответ дан 23 November 2019 в 04:19

Используйте os.chdir() вместо этого.

Кроме проблем, упомянутых в существующих ответах, я не предпочел бы использовать shell=True, ни subprocess.call() здесь для изменения каталога.

Python поступает по-своему изменяющегося каталога в os.chdir() (не забывайте к import os). ~ ("домашний") может быть определен несколькими способами, a.o. os.environ["HOME"].

Причины предпочесть, чтобы более чем shell=True могли быть считаны a.o. здесь

3
ответ дан 23 November 2019 в 04:19

Обратите внимание, что использование os.chdir () может вызвать непреднамеренные побочные эффекты, например если вы используете многопоточность . Все методы подпроцесса предоставляют аргумент ключевого слова cwd , который будет запускать запрошенный подпроцесс в этом каталоге, не затрагивая другие части вашего процесса python.

0
ответ дан 20 March 2020 в 17:17

Другие вопросы по тегам:

Похожие вопросы: