Использование подстановочного знака подпроцесса Python - PullRequest
53 голосов
/ 03 апреля 2012
import os

import subprocess

proc = subprocess.Popen(['ls','*.bc'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)

out,err = proc.communicate()

print out

Этот скрипт должен печатать все файлы с суффиксом .bc, но возвращает пустой список.Если я делаю ls * .bc вручную в командной строке, это работает.Выполнение ['ls', 'test.bc'] внутри скрипта также работает, но по какой-то причине символ звезды не работает .. Есть идеи?

Ответы [ 2 ]

64 голосов
/ 03 апреля 2012

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

 proc = subprocess.Popen('ls *.bc', shell=True,
                                    stdout=subprocess.PIPE,
                                    stderr=subprocess.PIPE)
52 голосов
/ 03 апреля 2012

Расширение глобуса * является частью оболочки, но по умолчанию subprocess не отправляет ваши команды через оболочку, поэтому команда (первый аргумент, ls) выполняется, тогда в качестве аргумента используется литерал *.

Это хорошо, см. блок предупреждений в разделе «Часто используемые аргументы» документации по подпроцессам. В основном речь идет о последствиях для безопасности, но также помогает избежать глупых ошибок в программировании (так как не нужно волноваться о магических символах оболочки)

Моя основная жалоба на shell=True обычно подразумевает, что существует более эффективный способ решения проблемы - в вашем примере вы должны использовать модуль glob :

import glob
files = glob.glob("*.bc")
print files # ['file1.bc', 'file2.bc']

Это будет быстрее (без затрат на запуск процесса), более надежным и кроссплатформенным (не зависит от платформы, имеющей команду ls)

...