Python stdout не корректно сбрасывается после вызова curses - PullRequest
4 голосов
/ 14 сентября 2010

У меня есть программа, которая использует проклятия, а затем возвращается к основному сценарию для дальнейшей обработки. После того, как он вернется, мой последующий вывод в stdout не появится, пока его не будет много (например, тысячи байт).

Я свел проблему к очень простой программе, которая надежно дает сбой:

import curses
import time

curses.initscr()
curses.endwin()

print "Hello world!"
time.sleep(5)

Если я закомментирую два вызова проклятий, «Привет, мир!» печатает до задержки. Если я вставлю их, он будет напечатан после задержки (при выходе из скрипта).

Ответы [ 4 ]

3 голосов
/ 14 сентября 2010

Вызов curses.endwin() "возвращает стандартный ввод / вывод обратно в нормальное состояние" ... что, к сожалению, означает "буферизованный" (вы можете считать, что это ошибка в curses и отправить ошибку на трекер Python).

Чтобы гарантировать, что стандартный вывод не буферизован,

import os

sys.stdout = os.fdopen(0, 'w', 0)

(Вы можете поставить import os в начале или в курсе; переназначение sys.stdout должно идти сразу после endwin звонок).

1 голос
/ 26 марта 2015

более понятным способом:

import sys
import curses

correct_stdout = sys.stdout    # remember correct

curses.initscr()
curses.endwin()

sys.stdout = correct_stdout    # restore correct
1 голос
/ 14 сентября 2010

Алекс опередил меня (он знал, что я должен был это выяснить), но я написал этот отличный менеджер контекста, который вы могли бы использовать.

import curses
import time
import os
import sys


class CursesStdout(object):
    def __enter__(self):
        pass

    def __exit__(self, *args):
        sys.stdout = sys.__stdout__ = os.fdopen(sys.__stdout__.fileno(), 'w', 0)

with CursesStdout():
    curses.initscr()
    curses.endwin()


print "Hello world!"
time.sleep(2)

Я изменяю sys.__stdout__ напрямую, потому что когда вы смотрите на источник в curses/__init__.py, вы видите, что функция initscr передает этот файловый дескриптор в код C, и поэтому я сохраняю его для сброса в нормальное состояние.

0 голосов
/ 14 сентября 2010

Я обнаружил, что это зависит от системы / библиотеки. На моей машине с Windows (проклятия от http://www.lfd.uci.edu/~gohlke/pythonlibs/) он мигает, а затем спит, но в Linux он мигает после сна. Я думаю, вы можете просто использовать: sys.stdout.flush() например:

print "Hello world!"
sys.stdout.flush()
time.sleep(5)

(может быть лучше сделать какую-нибудь функцию "print & flush")

...