Python: fork, pipe and exec

前端 未结 3 1938
天命终不由人
天命终不由人 2021-01-03 02:47

I want to execute a program in a python application, it will run in the background but eventually come to the foreground.

A GUI is used to interact with it. But con

3条回答
  •  半阙折子戏
    2021-01-03 03:06

    First, the python subprocess module is the correct answer.

    As an subprocess example:

    import subprocess
    x = subprocess.check_output(["echo","one","two","three"])
    

    Where x will be the output (python3 bytes class: x.decode('utf-8') for string)

    Note that this will NOT duplicate stderr. If you need stderr as well, you can do something like:

    x = subprocess.check_output(["bash","-c", 'echo foo; echo bar >&2'],stderr=subprocess.STDOUT)
    

    Of course, there are many other ways of capturing stderr, including to a different output variable.

    Using direct control

    However, if you are doing something tricky and need to have direct control, @Beginner's answer is flawed in a few ways: os._exit(0) was included which immediately causes the child to exit, rendering everything else pointless. No os.execve() rendering the primary goal of the question pointless. No way to access the child's stdout/stderr as another question goal.

    import os
    rside, wside = os.pipe()
    if not os.fork():
        # Child
    
        os.close(rside)
        # Make stdout go to parent
        os.dup2(wside, 1)
        # Make stderr go to parent
        os.dup2(wside, 2)
        # Optionally make stdin come from nowhere
        devnull = os.open("/dev/null", os.O_RDONLY)
        os.dup2(devnull, 0)
        # Execute the desired program
        os.execve("/bin/bash",["/bin/bash","-c","echo stdout; echo stderr >&2"],os.environ)
        print("Failed to exec program!")
        sys.exit(1)
    
    # Parent
    os.close(wside)
    pyrside = os.fdopen(rside)
    
    for line in pyrside:
       print("Child (stdout or stderr) said: <%s>"%line)
    
    # Prevent zombies!  Reap the child after exit
    pid, status = os.waitpid(-1, 0)
    print("Child exited: pid %d returned %d"%(pid,status))
    

提交回复
热议问题