Вопрос

Это следующий вопрос здесь в частности, в отношении его отвечать.


Из модуля Python я называю Привет, мир исполняемый файл, который просто печатает Hello World к Stdout. Я заинтересован в перенаправлении этой выводы на питон StringIO и столкнулся с это Ответ, который почти приводит меня к решению.

Критической частью этого ответа является этот сегмент кода:

1. def redirect_stdout():
2.     print "Redirecting stdout"
3.     sys.stdout.flush() # <--- important when redirecting to files
4.     newstdout = os.dup(1)
5.     devnull = os.open('/dev/null', os.O_WRONLY)
6.     os.dup2(devnull, 1)
7.     os.close(devnull)
8.     sys.stdout = os.fdopen(newstdout, 'w')

Также я хотел бы восстановить Stdout, как это было до перенаправления.

Вопросы

  1. Что именно происходит в функции выше?
    • Что такое dup а также dup2 делает?
    • Что такое /dev/null?
    • Что делает строка 8? (sys.stdout = os.fdopen(newstdout, 'w'))
  2. Как я могу хранить stdout в StringIO объект?
  3. Как я могу восстановить stdout после вызова моего Привет, мир программа?

Я почти уверен, что, как только у меня будет ответ на мой вопрос 1, ответы на вопросы 2 и 3 будут легко. Я все равно решил опубликовать их, чтобы, возможно, подтолкнуть ответ на вопрос 1 в направлении, куда я хочу пойти.

Это было полезно?

Решение

Ниже я написал несколько дополнительных комментариев, которые должны прояснить, что происходит внутри redirect_stdout Функция:

def redirect_stdout():
    print "Redirecting stdout"
    sys.stdout.flush() # <--- important when redirecting to files

    # Duplicate stdout (file descriptor 1)
    # to a different file descriptor number
    newstdout = os.dup(1)

    # /dev/null is used just to discard what is being printed
    devnull = os.open('/dev/null', os.O_WRONLY)

    # Duplicate the file descriptor for /dev/null
    # and overwrite the value for stdout (file descriptor 1)
    os.dup2(devnull, 1)

    # Close devnull after duplication (no longer needed)
    os.close(devnull)

    # Use the original stdout to still be able
    # to print to stdout within python
    sys.stdout = os.fdopen(newstdout, 'w')

Одна важная вещь, которую нужно отметить, это то, что процесс получает три разных Файл дескрипторы из ОС при запуске:

  • Stdin: 0
  • stdout: 1
  • Stderr: 2

Как объяснено в комментариях, приведенный выше код использует функции Decriptor File для STDOUT и функций дупликации дескриптора файла, чтобы сделать трюк C -кода в использование другого Stdout, сохраняя при этом ссылку на исходный STDOUT в коде Python, чтобы иметь возможность печатать.

Другие советы

/dev/null это специальный файл устройства (все в Unix - это файл!), Который проглатывает все, что записано, как черная дыра. dup дублирует дескриптор файла. Если вы привыкли к Windows, дескриптор файла в UNIX - это специальное целое число, которое представляет собой открытый файл, это похоже на дескриптор файлов Windows.

Программа открывается /dev/null Для написания (только), получая копию дескриптора его файла, закрытие открытого файла (поскольку наличия дескриптора файла достаточно, чтобы Unix для записи в файл вам не нужно держать ресурсы открытыми), а затем назначать открытый файл в sys.stdout.

Запомнить sys является модулем Python, который представляет все виды системных ресурсов, таких как файловая система. Итак, в Unix sys.stdout будет представлять /dev/stdout т.е. система STDOUT ручей.

Итак, в целом этот код обманывает Python, чтобы думать, что /dev/null/ является STDOUT Так что теперь каждый раз, когда ваша программа пишет STDOUT С, скажем, print Заявление (функция в Python3), тогда он действительно будет писать /dev/null И вы никогда не увидите полученный текст на вашей консоли.

Видеть ручные страницы Для функций выполнения C, которые лежат в основе этих функций Python.

По сути, они дублируют дескриптор файла, либо в новый дескриптор файла (с dup()) или в дескриптор файла, указанный в вызове, с dup2().

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top