Подпроцесс Python Grep
Я пытаюсь использовать команду grep в python script с помощью модуля подпроцесса.
Вот что у меня есть:
userid = 'foo12'
p = subprocess.Popen(['grep', "%s *.log"%userid], stdout=subprocess.PIPE)
И он ничего не возвращает.
Я не совсем уверен, что я делаю неправильно, поэтому кто-то может объяснить. Текущий метод, который я использую для этого, заключается в добавлении shell = true, который позволяет выводить правильный вывод, но, как указывают страницы справки, он небезопасен. Мне нужна помощь, пытаясь сделать эту работу, чтобы мой script был небезопасным.
Ответы
Ответ 1
Я думаю, что вы столкнулись с двумя проблемами:
-
Этот вызов:
p = subprocess.Popen(['grep', "%s *.log"%userid]...
не будет работать так, как ожидалось, без shell=True
, потому что список аргументов передается непосредственно на os.execvp
, что требует, чтобы каждый элемент представлял собой одну строку, представляющую аргумент. Вы объединили два отдельных аргумента в одну строку (другими словами, grep интерпретирует "foo12 *.log
" как шаблон для поиска, а не шаблон + список файлов).
Вы можете исправить это, сказав:
p = subprocess.Popen(['grep', userid, '*.log']...)
-
Вторая проблема заключается в том, что, опять же без shell=True
, execvp
не знает, что вы подразумеваете под *.log
, и передает его непосредственно в grep, не проходя через механизм расширения подстановочных оболочек. Если вы не хотите использовать shell=True
, вы можете сделать что-то вроде:
import glob
args = ['grep', userid]
args.extend(glob.glob('*.log')
p = subprocess.Popen(args, ...)
Ответ 2
Вот два тестируемых фрагмента кода для модели:
>>> 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, обязательно поместите всю команду в одну строку, а не в список отдельных полей.
Ответ 3
Я предполагаю, что вы хотите grep для 'foo12' во всех файлах, заканчивающихся '.log', чтобы заставить это работать только с subprocess
, вам нужно будет изменить свой код на следующее:
userid = 'foo12'
p = subprocess.Popen('grep %s *.log' % userid, stdout=subprocess.PIPE, shell=True)
shell=True
необходим для расширения подстановочных знаков, и когда эта опция установлена, вам нужно предоставить строковую команду вместо списка.
Кроме того, убедитесь, что когда вы предоставляете список аргументов, каждый из которых является отдельной записью в списке, ваш исходный код был бы эквивалентен следующему:
grep 'foo12 *.log'