在python中嵌入bash

Embed bash in python

我正在写一个python脚本,时间不多了。我需要在bash中做一些我非常熟悉的事情,所以我想知道如何将一些bash行嵌入到一个python脚本中。

谢谢


最理想的方法是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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')

您也可以向ScriptException中添加一个不错的__str__方法(您肯定需要它来调试脚本),但我把它留给读者。

如果不使用stdout=subprocess.PIPE等,脚本将直接附加到控制台。例如,如果您有来自ssh的密码提示,那么这真的很方便。因此,您可能需要添加标志来控制是否要捕获stdout、stderr和stdin。


如果要调用系统命令,请使用子进程模块。


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

要为你做吗?

编辑:关于可读性

是的,当然,你可以让它更可读

1
2
3
4
5
6
7
import os
script ="""
echo $0
ls -l
echo done
"""

os.system("bash -c '%s'" % script)

edit2:关于宏,没有一个python没有达到我所知的程度,而是介于

1
2
3
4
5
6
7
import os
def sh(script):
    os.system("bash -c '%s'" % script)

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

上一个例子,你基本上得到了你想要的(但是你必须考虑到一些辩证的限制)


当bash命令很简单并且没有括号、逗号和引号时,subprocess和os.system()可以正常工作。嵌入复杂bash参数的简单方法是在python脚本末尾添加带有唯一字符串注释的bash脚本,并使用简单的os.system()命令跟踪并转换为bash文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/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*

假设主机系统支持该命令:

1
2
import os
os.system('command')

如果您有一个长命令或一组命令。您可以使用变量。如:

1
2
3
4
5
6
7
8
# 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)

如前所述,您可以使用os.system();它既快速又脏,但是它很容易使用,并且适用于大多数情况。它实际上是到c system()函数的映射。

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

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


你可以用ipython作为外壳。在网站上搜索:"i python-bash替换",或者看这里:stackoverflow.com/questions/209470/can-i-use-python-as-a-bash-replacement。您可以从脚本调用ipython:

1
#!/usr/bin/ipython --profile=pysh

还有commands模块,可以对输出进行更多的控制:https://docs.python.org/2/library/commands.html网站


我创建苏丹是为了解决你想做的事情。它没有任何外部依赖关系,并试图尽可能轻,并提供了一个用于bash的pythonic接口。

https://github.com/aeroxis/sultan