Подпроцесс Python Grep - PullRequest
       19

Подпроцесс Python Grep

12 голосов
/ 31 октября 2011

Я пытаюсь использовать команду grep в скрипте Python с помощью модуля подпроцесса.

Вот что у меня есть:

userid = 'foo12'
p = subprocess.Popen(['grep', "%s *.log"%userid], stdout=subprocess.PIPE)

И это ничего не возвращает. Я не совсем уверен, что я делаю неправильно, поэтому кто-то может объяснить, пожалуйста. Текущий метод, который я использую и который работает, заключается в добавлении shell = true, который заставляет выводить правильный вывод, но, как указали страницы справки, это небезопасно. Мне нужна помощь, чтобы попытаться сделать это так, чтобы мой сценарий не был небезопасным.

Ответы [ 3 ]

11 голосов
/ 31 октября 2011

Я думаю, что вы столкнулись с двумя проблемами:

  1. Этот звонок:

    p = subprocess.Popen(['grep', "%s *.log"%userid]...
    

    не будет работать должным образом без shell=True, поскольку список аргументов передается непосредственно в os.execvp, что требует, чтобы каждый элемент представлял собой одну строку, представляющую аргумент. Вы сжали два отдельных аргумента вместе в одну строку (другими словами, grep интерпретирует "foo12 *.log" как шаблон для поиска, а не шаблон + список файлов) .

    Вы можете исправить это, сказав:

    p = subprocess.Popen(['grep', userid, '*.log']...)
    
  2. Вторая проблема заключается в том, что, опять же, без shell=True, execvp не знает, что вы подразумеваете под *.log, и передает его непосредственно в grep, не проходя через механизм расширения с подстановочными знаками оболочки. Если вы не хотите использовать shell=True, вы можете вместо этого сделать что-то вроде:

    import glob
    args = ['grep', userid]
    args.extend(glob.glob('*.log')
    p = subprocess.Popen(args, ...)
    
9 голосов
/ 31 октября 2011

Вот два проверенных фрагмента кода для модели:

>>> print subprocess.check_output(['grep', 'python', 'api_talk.txt'])
Discuss python API patterns
Limitations of python
Introspection in python

>>> print subprocess.check_output('grep python *.txt', shell=True)

Используйте последнее, если вы хотите, чтобы оболочка выполняла подстановочные знаки для вас. Если shell равно True , обязательно поместите всю команду в одну строку, а не в список отдельных полей.

5 голосов
/ 31 октября 2011

Я предполагаю, что вы хотите использовать grep для 'foo12' во всех файлах, заканчивающихся на '.log', чтобы заставить его работать только с subprocess, вам нужно изменить код на следующее:

userid = 'foo12'
p = subprocess.Popen('grep %s *.log' % userid, stdout=subprocess.PIPE, shell=True)

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

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

grep 'foo12 *.log'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...