Ada contextlib.redirect_stdout()
fungsi dalam Python 3.4:
from contextlib import redirect_stdout
with open('help.txt', 'w') as f:
with redirect_stdout(f):
print('it now prints to `help.text`')
Ini mirip dengan:
import sys
from contextlib import contextmanager
@contextmanager
def redirect_stdout(new_target):
old_target, sys.stdout = sys.stdout, new_target # replace sys.stdout
try:
yield new_target # run some code with the replaced stdout
finally:
sys.stdout = old_target # restore to the previous value
yang dapat digunakan pada versi Python sebelumnya. Versi terakhir tidak dapat digunakan kembali . Itu bisa dibuat satu jika diinginkan.
Itu tidak mengarahkan stdout di tingkat deskriptor file misalnya:
import os
from contextlib import redirect_stdout
stdout_fd = sys.stdout.fileno()
with open('output.txt', 'w') as f, redirect_stdout(f):
print('redirected to a file')
os.write(stdout_fd, b'not redirected')
os.system('echo this also is not redirected')
b'not redirected'
dan 'echo this also is not redirected'
tidak diarahkan ke output.txt
file.
Untuk mengarahkan ulang di tingkat deskriptor file, os.dup2()
dapat digunakan:
import os
import sys
from contextlib import contextmanager
def fileno(file_or_fd):
fd = getattr(file_or_fd, 'fileno', lambda: file_or_fd)()
if not isinstance(fd, int):
raise ValueError("Expected a file (`.fileno()`) or a file descriptor")
return fd
@contextmanager
def stdout_redirected(to=os.devnull, stdout=None):
if stdout is None:
stdout = sys.stdout
stdout_fd = fileno(stdout)
# copy stdout_fd before it is overwritten
#NOTE: `copied` is inheritable on Windows when duplicating a standard stream
with os.fdopen(os.dup(stdout_fd), 'wb') as copied:
stdout.flush() # flush library buffers that dup2 knows nothing about
try:
os.dup2(fileno(to), stdout_fd) # $ exec >&to
except ValueError: # filename
with open(to, 'wb') as to_file:
os.dup2(to_file.fileno(), stdout_fd) # $ exec > to
try:
yield stdout # allow code to be run with the redirected stdout
finally:
# restore stdout to its previous value
#NOTE: dup2 makes stdout_fd inheritable unconditionally
stdout.flush()
os.dup2(copied.fileno(), stdout_fd) # $ exec >&copied
Contoh yang sama berfungsi sekarang jika stdout_redirected()
digunakan alih-alih redirect_stdout()
:
import os
import sys
stdout_fd = sys.stdout.fileno()
with open('output.txt', 'w') as f, stdout_redirected(f):
print('redirected to a file')
os.write(stdout_fd, b'it is redirected now\n')
os.system('echo this is also redirected')
print('this is goes back to stdout')
Output yang sebelumnya dicetak pada stdout sekarang pergi output.txt
selama stdout_redirected()
manajer konteks aktif.
Catatan: stdout.flush()
tidak menyiram buffer C stdio di Python 3 di mana I / O diimplementasikan langsung pada read()
/ write()
system calls. Untuk menyiram semua aliran output C stdio yang terbuka, Anda dapat memanggil libc.fflush(None)
secara eksplisit jika beberapa ekstensi C menggunakan I / O berbasis stdio:
try:
import ctypes
from ctypes.util import find_library
except ImportError:
libc = None
else:
try:
libc = ctypes.cdll.msvcrt # Windows
except OSError:
libc = ctypes.cdll.LoadLibrary(find_library('c'))
def flush(stream):
try:
libc.fflush(None)
stream.flush()
except (AttributeError, ValueError, IOError):
pass # unsupported
Anda bisa menggunakan stdout
parameter untuk mengarahkan aliran lain, tidak hanya sys.stdout
mis., Untuk menggabungkan sys.stderr
dan sys.stdout
:
def merged_stderr_stdout(): # $ exec 2>&1
return stdout_redirected(to=sys.stdout, stdout=sys.stderr)
Contoh:
from __future__ import print_function
import sys
with merged_stderr_stdout():
print('this is printed on stdout')
print('this is also printed on stdout', file=sys.stderr)
Catatan: stdout_redirected()
mencampur I / O buffer ( sys.stdout
biasanya) dan I / O unbuffered (operasi pada deskriptor file secara langsung). Hati-hati, mungkin ada masalah buffering .
Untuk menjawab, hasil edit Anda: Anda dapat menggunakan python-daemon
untuk daemonisasi skrip Anda dan menggunakan logging
modul (seperti yang disarankan @ erikb85 ) alih-alih print
pernyataan dan hanya mengarahkan stdout untuk skrip Python Anda yang sudah berjalan lama yang Anda jalankan gunakan nohup
sekarang.
script.p > file