Lendo o stdin do programa python iniciado via ssh no terminal

1

Eu tenho este pequeno script python3 test.py :

import sys

print('test1')
test1 = sys.stdin.read()
print('test2')
test2 = sys.stdin.read()

print(test1)
print(test2)

E eu gostaria de rodar este script remotamente via ssh assim:

ssh srvid 'cd; python3 test.py'

Espero que o programa imprima test1 , depois espere pela entrada e imprima test2 e espere novamente pela entrada.

Mas o comportamento é um pouco diferente:

ssh srvid 'cd; python3 test.py'
hell
test1
test2
hell

O programa primeiro esperou pela entrada. Eu digitei hell e pressionei enter e, em seguida, ctr + d para eof. O script não esperou pela segunda entrada e imprimiu test1 e test2 .

Parece que stdin / stdout estão de alguma forma bloqueados.

Eu tentei o mesmo exemplo no bash:

#!/bin/bash

echo "Hello world";
read test;
echo "helloworld 2";
read test2;
echo $test;
echo $test2;

Quando invoquei este script via ssh, tudo funcionou como estou esperando.

Alguém pode me ajudar?

    
por JoshuaBoshi 30.09.2011 / 23:25

1 resposta

1

Isso se deve a uma convenção da libc para armazenamento em buffer do stdio. Se stdout é um tty, normalmente é um buffer de linha; totalmente em buffer de outra forma.

Como outros têm sugerido, passar o sinalizador -t para ssh força a alocação do psuedo-tty e você obtém o buffer de linha como resultado.

No entanto, você também pode liberar explicitamente o stdout para obter um resultado semelhante, como em:

import sys

print('test1')
sys.stdout.flush()
test1 = sys.stdin.readline() # ctrl+d and .read() effectively closes 
print('test2')               # stdin for the duration
sys.stdout.flush()
test2 = sys.stdin.readline()

print(test1)
print(test2)
# flushing happens implicitly when the stream is closed

Outra opção seria executar python no modo totalmente sem buffer com o -u flag, como em

ssh srvid 'cd; python3 -u test.py'

Soluções alternativas adicionais podem ser encontradas em essa pergunta sobre o stackoverflow .

The program first waited for input. I have entered hell and pressed enter and then ctr+d for eof. Script did not wait for second input, and printed out test1 and test2.

Tenho certeza de que o script não parou na segunda entrada porque você enviou um EOF durante o primeiro.

FWIW, eu provavelmente escreveria o python dessa maneira, a menos que você precise de entrada de várias linhas. É uma comparação mais próxima do seu exemplo básico, o IMO.

#!/usr/bin/env python3

print('test1')
test1 = input() # raw_input() in python 2.x
print('test2')         
test2 = input()

print(test1)
print(test2)
    
por 04.10.2011 / 01:06

Tags