Использование файловых дескрипторов для связи между процессами - PullRequest
0 голосов
/ 22 сентября 2010

У меня есть следующий код 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)

Как я могу переписать его, чтобы он не использовал Popen и cat?Мне нужен способ передачи данных из функции оболочки, запущенной в интерактивной оболочке, которая не будет смешиваться с данными, созданными другими функциями (поэтому я не могу использовать stdout или stderr).

1 Ответ

1 голос
/ 23 сентября 2010

Хорошо, я думаю, что теперь у меня есть ответ на ваш вопрос, и я вижу два разных подхода, которые вы могли бы использовать.

Если вы абсолютно хотите предоставить оболочке в дочернем процессе уже открытый дескриптор файла, тогда вы можете заменить Popen() из cat вызовом os.pipe(). Это даст вам подключенную пару реальных файловых дескрипторов (не объектов Python file). Все, что записано во второй файловый дескриптор, может быть прочитано из первого, заменив ваш фальсифицированный жюри cat -pipe. (Хотя "кот-труба" интересно сказать ...). Пара сокетов (socket.socketpair()) также может быть использована для достижения того же конца, если вам нужна двунаправленная пара.

Кроме того, вы могли бы упростить свою жизнь еще больше, используя именованный канал (он же FIFO). Если вы не знакомы с этим средством, именованный канал - это однонаправленный канал, расположенный в пространстве имен файловой системы. Функция os.mkfifo() создаст канал в файловой системе. Затем вы можете открыть канал для чтения в вашем основном процессе и открыть его для записи / прямого вывода на него из вашего дочернего процесса оболочки. Это должно упростить ваш код и открыть возможность использования существующей библиотеки, такой как Pexpect , для взаимодействия с оболочкой.

...