0

次のpythonコードがあります:

import pty
import subprocess
os=subprocess.os
from subprocess import PIPE
import time
import resource

pipe=subprocess.Popen(["cat"], stdin=PIPE, stdout=PIPE, stderr=PIPE, \
                      close_fds=True)
skip=[f.fileno() for f in (pipe.stdin, pipe.stdout, pipe.stderr)]
pid, child_fd = pty.fork()
if(pid==0):
    max_fd=resource.getrlimit(resource.RLIMIT_NOFILE)[0]
    fd=3
    while fd<max_fd:
        if(fd not in skip):
            try:
                os.close(fd)
            except OSError:
                pass
            fd+=1
        enviroment=os.environ.copy()
        enviroment.update({"FD": str(pipe.stdin.fileno())})
        os.execvpe("zsh", ["-i", "-s"], enviroment)
else:
    os.write(child_fd, "echo a >&$FD\n")
    time.sleep(1)
    print pipe.stdout.read(2)

Popenand を使用しないように書き換えるにはどうすればよいcatですか? 対話型シェルで実行されているシェル関数から、他の関数によって作成されたデータと混合しないデータを渡す方法が必要です (したがって、stdout または stderr を使用できません)。

4

1 に答える 1

1

わかりました、私はあなたの質問を理解したと思います.2つの異なるアプローチを取ることができます.

子プロセスのシェルにすでに開いているファイル記述子を絶対に提供したい場合は、Popen()catを の呼び出しに置き換えることができますos.pipe()fileこれにより、接続された実際のファイル記述子 (Pythonオブジェクトではありません) のペアが得られます。2番目のファイル記述子に書き込まれたものはすべて、最初のファイル記述子から読み取ることができ、陪審員のパイプを置き換えますcat。(「猫パイプ」と言うのは楽しいですが...)。socket.socketpair()双方向のペアが必要な場合は、ソケット ペア ( ) を使用して同じ目的を達成することもできます。

または、名前付きパイプ (別名 FIFO) を使用して、さらに簡単にすることもできます。この機能に慣れていない場合、名前付きパイプは、ファイル システムの名前空間にある単方向パイプです。このos.mkfifo()関数は、ファイルシステムにパイプを作成します。次に、プライマリ プロセスで読み取り用にパイプを開き、シェルの子プロセスからの書き込み/直接出力用にパイプを開くことができます。これにより、コードが簡素化され、Pexpectなどの既存のライブラリを使用してシェルとやり取りするオプションが開かれます。

于 2010-09-23T03:26:05.863 に答える