Вставить Bash в Python - PullRequest
       21

Вставить Bash в Python

17 голосов
/ 16 апреля 2010

Я пишу скрипт на Python, и у меня заканчивается время. Мне нужно сделать некоторые вещи, которые я хорошо знаю, в bash, поэтому мне просто интересно, как я могу встроить некоторые строки bash в скрипт Python.

Спасибо

Ответы [ 9 ]

30 голосов
/ 16 апреля 2010

Идеальный способ сделать это:

def run_script(script, stdin=None):
    """Returns (stdout, stderr), raises error on non-zero return code"""
    import subprocess
    # Note: by using a list here (['bash', ...]) you avoid quoting issues, as the 
    # arguments are passed in exactly this order (spaces, quotes, and newlines won't
    # cause problems):
    proc = subprocess.Popen(['bash', '-c', script],
        stdout=subprocess.PIPE, stderr=subprocess.PIPE,
        stdin=subprocess.PIPE)
    stdout, stderr = proc.communicate()
    if proc.returncode:
        raise ScriptException(proc.returncode, stdout, stderr, script)
    return stdout, stderr

class ScriptException(Exception):
    def __init__(self, returncode, stdout, stderr, script):
        self.returncode = returncode
        self.stdout = stdout
        self.stderr = stderr
        Exception.__init__('Error in script')

Вы также можете добавить хороший __str__ метод к ScriptException (он вам обязательно понадобится для отладки ваших скриптов) - но я оставлю это читателю.

Если вы не используете stdout=subprocess.PIPE и т. Д., Сценарий будет прикреплен непосредственно к консоли. Это действительно удобно, если у вас есть, например, запрос пароля от ssh. Поэтому вы можете захотеть добавить флаги, чтобы контролировать, хотите ли вы захватить stdout, stderr и stdin.

12 голосов
/ 16 апреля 2010

Если вы хотите вызывать системные команды, используйте модуль subprocess .

6 голосов
/ 16 апреля 2010

Есть

import os
os.system ("bash -c 'echo $0'")

собираешься сделать это для тебя?

РЕДАКТИРОВАТЬ: в отношении читабельности

Да, конечно, вы можете сделать его более читабельным

import os
script = """
echo $0
ls -l
echo done
"""
os.system("bash -c '%s'" % script)

EDIT2: что касается макросов, ни один питон не заходит так далеко, насколько я знаю, но между

import os
def sh(script):
    os.system("bash -c '%s'" % script)

sh("echo $0")
sh("ls -l")
sh("echo done")

и предыдущий пример, вы в основном получаете то, что хотите (но вы должны учесть некоторые диалектические ограничения)

4 голосов
/ 19 апреля 2016

subprocess и os.system () отлично работают, когда команды bash просты и не имеют скобок, запятых и кавычек. Простой способ встроить сложный аргумент bash - добавить скрипт bash в конец скрипта python с уникальными строковыми комментариями и использовать простые команды os.system () для хвоста и преобразования в файл bash.

#!/usr/bin/python
## name this file  "file.py"
import os
def get_xred(xx,yy,zz):
    xred=[]
####gaur###
    xred.append([     zz[9] ,  zz[19] ,  zz[29]     ])
    xred.append([     zz[9] ,  xx[9]  ,  yy[9]      ])
    xred.append([     zz[10],  zz[20] ,  zz[30]     ])
    xred.append([     zz[10],  xx[10] ,  yy[10]     ])
###nitai###
    xred=np.array(xred)
    return xred
## following 3 lines executes last 6 lines of this file.
os.system("tail -n 6 file.py >tmpfile1")
os.system("sed 's/###123//g' tmpfile1>tmpfile2")
os.system("bash tmpfile2")
###### Here ###123 is a unique string to be removed
###123#!/bin/sh
###123awk '/###gaur/{flag=1;next}/###nitai/{flag=0} flag{print}' file.py >tmp1
###123cat tmp1 | awk '{gsub("xred.append\\(\\[","");gsub("\\]\\)","");print}' >tmp2
###123awk 'NF >0' tmp2 > tmp3
###123sed '$d' tmp3 |sed '$d' | sed '$d' >rotation ; rm tmp*
3 голосов
/ 16 апреля 2010

Предполагается, что команда поддерживается хост-системой:

import os
os.system('command')

Если у вас длинная команда или набор команд. Вы можете использовать переменные. например:

# this simple line will capture column five of file.log
# and then removed blanklines, and gives output in filtered_content.txt.

import os

filter = "cat file.log | awk '{print $5}'| sed '/^$/d' > filtered_content.txt"

os.system(filter)
1 голос
/ 22 марта 2013

Как уже упоминалось, вы можете использовать os.system (); это быстро и грязно, но это легко использовать и работает в большинстве случаев. Это буквально отображение функции C system ().

http://docs.python.org/2/library/os.html#os.system

http://www.cplusplus.com/reference/cstdlib/system/

0 голосов
/ 01 сентября 2016

Я создал Султана, чтобы адресовать именно то, что вы пытаетесь сделать. Он не имеет каких-либо внешних зависимостей и пытается быть как можно более легким и предоставляет Pythonic интерфейс для Bash.

https://github.com/aeroxis/sultan

0 голосов
/ 13 августа 2014

Вы можете использовать IPython в качестве оболочки. Искать в Интернете: "замена ipython bash", или посмотрите здесь: stackoverflow.com / questions / 209470 / can-i-use-python-as-a-bash-replace . Вы можете вызвать IPython из скрипта:

#!/usr/bin/ipython --profile=pysh
0 голосов
/ 16 апреля 2010

Существует также модуль commands для большего контроля над выходом: https://docs.python.org/2/library/commands.html

...