Перенаправить stdout от python для c вызовы
-
26-10-2019 - |
Вопрос
Это следующий вопрос здесь в частности, в отношении его отвечать.
Из модуля 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, как это было до перенаправления.
Вопросы
- Что именно происходит в функции выше?
- Что такое
dup
а такжеdup2
делает? - Что такое
/dev/null
? - Что делает строка 8? (
sys.stdout = os.fdopen(newstdout, 'w')
)
- Что такое
- Как я могу хранить stdout в
StringIO
объект? - Как я могу восстановить 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()
.