Вывод сценариев Python отображается только в конце при использовании SSH? - PullRequest
4 голосов
/ 25 февраля 2010

Я запускаю скрипт для управления процессами на удаленной (SSH) машине. Давайте назовем это five.py

#!/usr/bin/python
import time, subprocess

subprocess.call('echo 0',shell=True)
for i in range(1,5):
   time.sleep(1)
   print(i)

Если я сейчас запусту

ssh user@host five.py

Хотелось бы увидеть вывод

0
1
2
3
4

появляется в моем стандарте секунду за секундой (как это происходит, если выполняется локально) .. Что происходит: я сразу получаю 0 из "echo", а остальное появляется только сразу после завершения всей программы. (Не помогает вкладывать 'five.py' в скрипт bash; вызывать его как 'python five.py'; или использовать 'print >> sys.stdout, i').

Это должно быть связано с тем, как python пишет в стандартный вывод, поскольку другие программы ведут себя вполне нормально. Функциональное решение -

import time, subprocess
import sys

subprocess.call('echo 0',shell=True)
for i in range(1,5):
  time.sleep(1)
  sys.stdout.write(str(i)+'\n')
  sys.stdout.flush()

Но должно быть лучшее решение, чем изменение всех моих операторов печати!

Ответы [ 4 ]

5 голосов
/ 26 февраля 2010

Вы можете добавить -u к строке Шебанга, как намекнул межджай.

#!/usr/bin/python -u

Вы также можете открыть стандартный вывод с отключенной буферизацией или установить буферизацию строки

import os,sys
sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0) # no buffering
sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 1) # line buffering

Обычно хорошая буферизация строки

2 голосов
/ 25 февраля 2010

Возможное решение в другой теме , предлагает использовать

ssh -t user@host ./five.py

который подделывает терминал. Единственный недостаток, печать по ssh

Connection to host closed.

дополнительно.

0 голосов
/ 26 февраля 2010

Одна вещь, на которую вы можете обратить внимание, поскольку вы уже используете Python, - это Paramiko , гораздо более приятный способ выполнения удаленной работы по SSH. Вот статья о том, как я использую ее в ее самой простой форме.

0 голосов
/ 25 февраля 2010

Вы можете заменить объект sys.stdout, чтобы он автоматически сбрасывался после каждой записи. Это также повлияет на оператор print. Пример взят из этого ответа :

class flushfile(object):
    def __init__(self, f):
        self.f = f
    def write(self, x):
        self.f.write(x)
        self.f.flush()

import sys
sys.stdout = flushfile(sys.stdout)

Редактировать: Другой вариант - запустить Python с параметром -u, который заставит ввод и вывод быть небуферизованными.

...