Друзья здравствуйте,
Хочу поделиться своим опытом по поводу ответа на вопрос:
Как запускать команды bash (в Linux) из python?Первый вопрос, который может возникнуть - для чего использовать другой язык, если всё (или почти всё) можно реализовать при помощи
pyton?
Ответ прост - время выполнения нашего кода. Это пожалуй самый главный, решающий фактор для нас, так как мы с Вами знаем, что процессор и другие компоненты в ресивере несколько уступают по производительности настольным компьютерам. Именно поэтому я рассматриваю вариант использования
bash в качестве реального инструмента при программировании для
enigma2, особенно если дело касается обработки большого объёма данных, как например данных
EPG.
Ну и в качестве второго аргумента приведу, что иногда на
bash можно сделать более эффективно и быстрее чем на
python. Например при обработке срок, используя
sed.
Итак приступим к рассмотрению нашего основного вопроса:
Как Вы наверное все знаете, в
python существует библиотека для этих целей под названием
os И функция
os.system() выполняет всё наши команды. И в качестве результата возвратит код успешности завершённого процесса.
Однако этот вариант хорош в том случае, когда нам нет необходимости в возврате результата из командной строки.
Если же нам необходимо получить результат выполнения из командной строки, то здесь нам
python даёт другой способ: функцию
Popen из класса
subprocess.
Вот об этом варианте я и хочу рассказать, чтобы в последствии Вы не сталкивались с теми же трудностями, что и я.
Итак функция работает следующим образом:
1. Формируем командную строку
2. Разбиваем ее на аргументы
3. Выполняем вызов функции
Popen() 4. Забираем результат функцией
communicate()[0]5. Разбираем ошибки в
communicate()[1].
Например мы хотим вывести список всех файлов в директории
/etc, для этого напишем следующий код:
Вам не разрешен просмотр кода. Войдите или Зарегистрируйтесь для просмотра.
На выходе получаем список файлов в переменной
listFiles разделённые символом новой строки.
Однако и этот вариант не всегда хорош.
Для примера, если мы хотим выполнить две или три команды подряд (например для фильтрации результата при помощи
grep или
sed), то переданный символ соединения команд «
|» не будет воспринят к исполнению и выполнение завершится ошибкой.
Здесь можно выйти из положения методом разделения потоков. Создать два потока и передать одному результат выполнения другого, как здесь:
Вам не разрешен просмотр кода. Войдите или Зарегистрируйтесь для просмотра.
Однако при выполнении трех и более команд по конвейеру в
bash - получается нагромождение кода. Что делать в этом случае?
Нашёл очень простое решение, описанное в документации)). Делаем следующее:
1. Формируем командную строку
3. Выполняем вызов функцией
Popen(), с обязательным аргументом
shell=True4. Забираем результат функцией
communicate()[0]5. Разбираем ошибки в
communicate()[1].
Другими словами, теперь мы не разбираем строку на аргументы, а пишем ее так как писали бы её в командном интерпретаторе
shell, типа
bash или в нашем случае
tuxboxВот сам код, как пример - выполним команду для получения значения аргумента из файла установок
enigma2:
(конечно же существуют классы работы с конфиг файлами - здесь привожу просто как пример, не более):
Вам не разрешен просмотр кода. Войдите или Зарегистрируйтесь для просмотра.
Как видно из примера мы полняем сразу три конвейерных команды
cat,
grep и
sed.
Таким образом получаем достаточно небольшой код и результат выполнения командной строки в нашу переменную для последующей обработки.
В документации, так же указывается, что первый вариант с разбиением командной строки на аргументы, позволяет нам избежать возможных ошибок при выполнении, так как мы контролируем ввод каждого параметра в ручную, а вот второй вариант таит в себе возможность допущения ошибок в самой командной строке. Потому и предупреждают о риске при его использовании.
И в тоже время, я думаю, что каждый уважающий себя начинающий программист, прежде чем что либо писать - проверит результат в интерпретаторе
shell и лишь затем вставит это в свой код на
python.
По крайней мере я в это верю
.
Если есть вопросы - пишите.