Python: fork, pipe and exec

前端 未结 3 1904
天命终不由人
天命终不由人 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 02:59

    That is not much complex in structure to build !

    Check this example

    if os.fork():
        os._exit(0)
        os.setsid()
        os.chdir("/")
        fd = os.open("/dev/null", os.O_RDWR)
        os.dup2(fd, 0)
        os.dup2(fd, 1)
        os.dup2(fd, 2)
    if fd 2:
        os.close(fd)
    

    This python code sets an id, changes the dir, opens a file and process and close !

    0 讨论(0)
  • 2021-01-03 03:04

    This is reasonably easy using the standard Python subprocess module:

    http://docs.python.org/py3k/library/subprocess.html

    0 讨论(0)
  • 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))
    
    0 讨论(0)
提交回复
热议问题