2015-02-13 6 views
1

Я новичок в модуле subprocess в python.Выполнение команд/программ с подпроцессом

В документации, предоставленной этот пример:

>>> subprocess.check_output(["echo", "Hello World!"]) 
b'Hello World!\n' 

Я попытался это:

>>> import subprocess 
>>> subprocess.check_output(["cd", "../tests", "ls"]) 
/usr/bin/cd: line 4: cd: ../tests: No such file or directory 
Traceback (most recent call last): 
    File "<input>", line 1, in <module> 
    File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/subprocess.py", line 620, in check_output 
    raise CalledProcessError(retcode, process.args, output=output) 
subprocess.CalledProcessError: Command '['cd', '../tests', 'ls']' returned non-zero exit status 1 

Я смущен, потому что это моя структура файла:

/proj 
     /cron 
     test_scheduler.py 
     /tests 
     printy.py 
     test1.py 
     test2.py 
     ... 

Это моя вторая также попытки:

>>> subprocess.check_output(["cd", "../tests", "python", "printy.py"]) 
/usr/bin/cd: line 4: cd: ../tests: No such file or directory 
Traceback (most recent call last): 
    File "<input>", line 1, in <module> 
    File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/subprocess.py", line 620, in check_output 
    raise CalledProcessError(retcode, process.args, output=output) 
subprocess.CalledProcessError: Command '['cd', '../tests', 'python', 'printy.py']' returned non-zero exit status 1 


>>> subprocess.check_output(["cd", "../tests;", "ls"]) 
/usr/bin/cd: line 4: cd: ../tests;: No such file or directory 
Traceback (most recent call last): 
    File "<input>", line 1, in <module> 
    File "/Library/Frameworks/Python.framework/Versions/3.4/lib/python3.4/subprocess.py", line 620, in check_output 
    raise CalledProcessError(retcode, process.args, output=output) 
subprocess.CalledProcessError: Command '['cd', '../tests;', 'ls']' returned non-zero exit status 1 

ответ

3

По возможности избегайте shell=True.

В этом случае вы, безусловно, можете избежать. Проблема, с которой вы сталкиваетесь: cd - это встроенная оболочка. Это не команда/программа/утилита, которая может быть вызвана извне. Вы должны быть в оболочке для cd для работы. Вместо этого вы можете изменить текущий каталог. Выполните команду. Затем вернитесь в исходный каталог.

Вам нужно сделать что-то вроде ниже:

pathBefore = os.getcwd() 
os.chdir("/path/to/your/directory") 
subprocess.check_output(["ls"]) 
os.chdir(pathBefore) # get back to the path we were in before 

UPDATE: A better approach pointed out by @JFSebastian is to use the additional cwd argument to check_output call.

+0

Возможно, поэтому я принял для написания Shell = True - как один из моих Первые попытки были cd. Теперь все части головоломки падают на место :) – BitTickler

+0

Если вы ничего не делаете с оболочкой, вам лучше не использовать 'shell = True'. Может показаться, что это облегчает жизнь для вас, но поверьте мне, это может дать вам головные боли в долгосрочной перспективе. – SuperSaiyan

+0

Правда. Мой единственный раз, когда я использовал python, был именно тогда, когда мне понадобился резервный скрипт, в то время как в любопытном настроении пытались использовать какой-то другой язык. Поэтому у меня нет более глубоких знаний о лучших методах работы с python. – BitTickler

1

Относительный путь к каталогу tests зависит от того, откуда выполняется сценарий. Я бы предложил позвонить subprocess.check_output(["pwd"]), чтобы проверить, где вы находитесь.

Также вы не можете комбинировать две команды в том же вызове, что и при попытке с ["cd", "../tests", "python", "printy.py"]. Вам необходимо сделать два отдельных звонка с ["cd", "../tests"] и ["python", "printy.py"] соответственно.

0

У вас отсутствует аргумент здесь, я думаю.
Вот отрывок из только питон скрипт я написал:

#!/usr/local/bin/python 

from subprocess import call 
... 
call("rm " + backupFolder + "*.bz2", shell=True) 

Пожалуйста, обратите внимание shell=True в конце этого вызова.

+0

Это не рекомендуется: http://stackoverflow.com/questions/3172470/actual-meaning-of-shell-true-in-subprocess – jonnybazookatone

1

Сообщение об ошибке не ясно:

/USR/бен/CD: строка 4: CD: ../tests: Нет такого файла или каталога

что вы успешно начали /usr/bin/cd, которая не удалась и напечатала сообщение об ошибке.

Если вы хотите запустить команду из ls../tests каталога вместо:

import os 
import subprocess 

cwd = os.path.join(get_script_dir(), '../tests') 
output = subprocess.check_output(['ls'], cwd=cwd) 

где get_script_dir().

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

Смежные вопросы