Embed bash in python

后端 未结 9 1220
别那么骄傲
别那么骄傲 2020-12-25 13:43

I am writting a Python script and I am running out of time. I need to do some things that I know pretty well in bash, so I just wonder how can I embed some bash lines into a

相关标签:
9条回答
  • 2020-12-25 13:55

    Is

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

    going to do it for you?

    EDIT: regarding readability

    Yes, of course, you can have it more readable

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

    EDIT2: regarding macros, no python does not go so far as far as i know, but between

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

    and previous example, you basically get what you want (but you have to allow for a bit of dialectical limitations)

    0 讨论(0)
  • 2020-12-25 13:57

    If you want to call system commands, use the subprocess module.

    0 讨论(0)
  • 2020-12-25 13:57

    The ideal way to do it:

    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')
    

    You might also add a nice __str__ method to ScriptException (you are sure to need it to debug your scripts) -- but I leave that to the reader.

    If you don't use stdout=subprocess.PIPE etc then the script will be attached directly to the console. This is really handy if you have, for instance, a password prompt from ssh. So you might want to add flags to control whether you want to capture stdout, stderr, and stdin.

    0 讨论(0)
  • 2020-12-25 13:58

    Assuming the command is supported by the host system:

    import os
    os.system('command')
    

    If you have a long command, or a set of commands. you can use variables. eg:

    # 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)
    
    0 讨论(0)
  • 2020-12-25 14:02

    As aforementioned, you could use os.system(); it's quick and dirty, bu it's easy to use and works for most cases. It's literally a mapping on to the C system() function.

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

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

    0 讨论(0)
  • 2020-12-25 14:04

    @Ian Bicking's answer is useful but it if only allow us to run scripts. Instead we can come up with a more flexible code where we can run command as well. I have a different approach from his.

    #!/usr/bin/env python3
    
    from subprocess import Popen, PIPE
    
    
    class BashCommandsException(Exception):
        def __init__(self, returncode, output, error_msg):
            self.returncode = returncode
            self.output = output
            self.error_msg = error_msg
            Exception.__init__('Error in executed command')
    
    
    def popen_communicate(cmd, stdout_file=None):
        """Acts similir to lib.run(cmd) but also returns the output message captures on
        during the run stdout_file is not None in case of nohup process writes its
        results into a file
        """
        cmd = list(map(str, cmd))  # all items should be string
        if stdout_file is None:
            p = Popen(cmd, stdout=PIPE, stderr=PIPE)
        else:
            with open(stdout_file, "w") as outfile:
                # output written into file, error will be returned
                p = Popen(cmd, stdout=outfile, stderr=PIPE, universal_newlines=True)
                output, error = p.communicate()
                p.wait()
                return p, output, error
    
        output, error = p.communicate()
        output = output.strip().decode("utf-8")
        error = error.decode("utf-8")
        return p, output, error
    
    
    def run(cmd):
        log_file = "/tmp/log.txt"
        # if log_file is not provided returned output will be stored in output
        p, output, error_msg = popen_communicate(cmd, log_file)
        if p.returncode != 0:
            raise BashCommandsException(p.returncode, output, error_msg, str(cmd))
        return output
    
    
    if __name__ == "__main__":
        # This could be any command you want to execute as you were in bash
        cmd = ["bash", "script_to_run.sh"]
        try:
            run(cmd)
        except Exception as e:
            print(e)
    
    
    0 讨论(0)
提交回复
热议问题