# subset of subprocess built-in module using posix_spawn rather than fork.
fsencoding = sys.getfilesystemencoding()
def __init__(self, args, stdin=None, stdout=None):
file_actions = posix_spawn.FileActions()
# child's stdout, child 2 parent pipe
c2pread, c2pwrite = os.pipe()
# attach child's stdout to writing en of c2p pipe
file_actions.add_dup2(c2pwrite, 1)
file_actions.add_close(c2pread)
# child's stdin, parent to child pipe
p2cread, p2cwrite = os.pipe()
# attach child's stdin to reading en of p2c pipe
file_actions.add_dup2(p2cread, 0)
file_actions.add_close(p2cwrite)
args = [s.encode(fsencoding) for s in args if type(s)==str]
self.pid = posix_spawn.posix_spawnp(args[0], args, file_actions=file_actions)
self.stdout = os.fdopen(c2pread)
self.stdin = os.fdopen(p2cwrite, 'w')
if self.returncode is None:
self.returncode = os.waitpid(self.pid, 0)[1]
if self.stdin is not None:
if self.stdout is not None:
stdoutdata = self.stdout.read()
if self.stdout is not None:
return (stdoutdata, stderrdata)
if self.stdin is not None:
if self.stdout is not None:
if self.returncode is None:
pid, ret = os.waitpid(self.pid, os.WNOHANG)
if self.stdin is not None:
if self.stdout is not None:
os.kill(self.pid, signal.SIGKILL)
if self.stdin is not None:
if self.stdout is not None:
if isinstance(args[0], str):
# splitting of arguments that cares about
# use of simple and double quotes
cmd = shlex.split(args[0])
elif isinstance(args[0], list) and len(args) == 1:
raise Exception("Wrong arguments passed to subprocess.call")
pid = posix_spawn.posix_spawnp(cmd[0], cmd)
return os.waitpid(pid, 0)
if __name__ == '__main__':
p = Popen(["tr", "abc", "def"], stdin=PIPE, stdout=PIPE)
p = Popen(["tr", "abc", "def"], stdin=PIPE, stdout=PIPE)