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