Использование подстановок подпроцесса Python
import os
import subprocess
proc = subprocess.Popen(['ls','*.bc'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out,err = proc.communicate()
print out
Этот script должен печатать все файлы с расширением .bc, но возвращает пустой список. Если я выполняю ls *.bc вручную в командной строке, он работает. Выполнение ['ls', 'test.bc'] внутри script работает, но по какой-то причине символ звезды не работает. Любые идеи?
Ответы
Ответ 1
Вам нужно предоставить shell=True
, чтобы выполнить команду через интерпретатор оболочки.
Если вы это сделаете, вы больше не сможете предоставлять список в качестве первого аргумента, потому что тогда будут переданы аргументы. Вместо этого укажите необработанную командную строку, как вы хотите, чтобы она была передана в оболочку:
proc = subprocess.Popen('ls *.bc', shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
Ответ 2
Расширение *
glob является частью оболочки, но по умолчанию subprocess
не отправляет ваши команды через оболочку, поэтому выполняется команда (первый аргумент, ls
), а затем литерал *
используется как аргумент.
Это хорошо, см. блок предупреждения в разделе "Часто используемые аргументы" в документах подпроцесса. Он в основном обсуждает последствия для безопасности, но также помогает избежать глупых ошибок программирования (так как нет волшебных символов оболочки, о которых нужно беспокоиться)
Моя основная жалоба с shell=True
заключается в том, что обычно существует лучший способ решить проблему - с вашим примером вы должны использовать the glob
модуль:
import glob
files = glob.glob("*.bc")
print files # ['file1.bc', 'file2.bc']
Это будет быстрее (без дополнительных затрат на запуск), более надежной и кросс-платформенной (не зависит от платформы, имеющей команду ls
)