Почему предоставление stdin для subprocess.Popen приводит к изменению того, что записано в stdout? - PullRequest
6 голосов
/ 01 марта 2010

Я использую подпроцесс Python. Откройте для выполнения некоторые FTP, используя двоичный клиент операционной системы хоста. Я не могу использовать ftplib или любую другую библиотеку по разным причинам.

Поведение бинарного файла, похоже, изменится, если я прикреплю обработчик stdin к экземпляру Popen. Например, используя FTP-клиент XP, который принимает текстовый файл команд для выдачи:

>>>from subprocess import Popen, PIPE  
>>>p = Popen(['ftp','-A','-s:commands.txt','example.com'], stdout=PIPE)  
>>>p.communicate()[0]  
'Connected to example.com.  
220 ProFTPD 1.3.1 Server (Debian) ...   
331 Anonymous login ok, send your complete email address as your password  
<snip>
ftp> binary  
200 Type set to I  
ftp> get /testfiles/100.KiB  
200 PORT command successful  
150 Opening BINARY mode data connection for /testfiles/100.KiB (102400 bytes)  
226 Transfer complete  
ftp: 102400 bytes received in 0.28Seconds 365.71Kbytes/sec.  
ftp> quit  
>>>

Commands.txt:

binary  
get /testfiles/100.KiB  
quit  

При вводе стандартного ввода все, что вы получаете в стандартном выводе:

>>>from subprocess import Popen, PIPE  
>>>p = Popen(['ftp','-A','-s:commands.txt','example.com'], stdin=PIPE, stdout=PIPE)  
>>>p.communicate()[0]  
'binary  
get /testfiles/100.KiB  
quit'  
>>>

Первоначально я думал, что это была странная особенность XP-клиента FTP, возможно, зная, что он не в интерактивном режиме, и поэтому ограничил его вывод. Однако, то же самое поведение происходит с ftp OS X - все ответы сервера отсутствуют в stdout, если указан stdin - что заставляет меня думать, что это нормальное поведение.

В Windows я могу использовать ключ -s для эффективного сценария ftp без использования stdin, но на других платформах для такого рода взаимодействия используется оболочка.

Версия Python 2.6.x на обеих платформах. Зачем указывать дескриптор stdin для изменения stdout и куда отправляются ответы сервера?

Ответы [ 2 ]

7 голосов
/ 01 марта 2010

Программа может использовать isatty(3) для обнаружения наличия tty на стандартном вводе.

4 голосов
/ 01 марта 2010

Мне кажется, я где-то читал (но не могу вспомнить), что клиент Windows ftp пришел из одной из оригинальных реализаций BSD. В этом он определенно разделяет некоторую связь с реализацией ftp в Mac OS X.

Для меня это связано не с Popen, а с реализацией клиентской ftp-программы, которая делает некоторые проверки контекста, в котором она запускается (чтобы увидеть, взаимодействует ли она с человеком или сценарием оболочки), используя isatty ( 3) как упомянул Игнасио в своем ответе. Это обычная практика для программ, которые могут использоваться в обоих контекстах. Хорошо известным примером является реализация GNU grep для опции --color = auto: она будет раскрашивать вывод, только если stdout является tty, а не если вывод grep передается в другую команду.

...