Python:fork,pipe和exec

问题描述 投票:2回答:3

我想在python应用程序中执行一个程序,它将在后台运行,但最终会到达前台。

GUI用于与之交互。但是控件是通过stdin和stdout上的控制台提供的。我希望能够使用我的应用程序的GUI来控制它,所以我的第一个想法是:

  • 叉子
  • 在父,dup2 stdin和stdout中访问它们
  • 执行孩子

这在python中是否可以轻松实现?有没有其他方法来实现我想要的,那会是什么?

python exec fork stdio dup
3个回答
6
投票

使用标准Python子进程模块相当容易:

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


4
投票

构建结构并不复杂!

检查此示例

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)

这个python代码设置一个id,更改dir,打开文件并处理和关闭!


1
投票

First, the python subprocess module is the correct answer.

作为子进程示例:

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

其中x将是输出(python3字节类:字符串的x.decode('utf-8')

请注意,这不会重复stderr。如果您还需要stderr,您可以执行以下操作:

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

当然,还有许多其他捕获stderr的方法,包括不同的输出变量。

Using direct control

但是,如果你正在做一些棘手的事情并且需要直接控制,那么@ Beginner的答案在某些方面存在缺陷:包括os._exit(0)会立即导致孩子退出,使其他一切变得毫无意义。没有os.execve()渲染问题的主要目标毫无意义。无法访问孩子的stdout / stderr作为另一个问题目标。

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))
© www.soinside.com 2019 - 2024. All rights reserved.