127 votes

Comment rediriger stdout à la fois vers un fichier et vers la console avec un script ?

Je veux exécuter un script de python et capturer la sortie sur un fichier texte ainsi que vouloir montrer sur la console.

Je veux le spécifier comme une propriété du script python lui-même. PAS pour utiliser la commande echo "hello world" | tee test.txt à l'invite de commande à chaque fois.

Dans script j'ai essayé :

sys.stdout = open('log.txt','w')

Mais cela n'affiche pas la sortie stdout à l'écran.

J'ai entendu parler du module de journalisation mais je n'ai pas eu de chance en utilisant ce module pour faire le travail.

199voto

Amith Koujalgi Points 2005

Vous pouvez utiliser la redirection du shell lors de l'exécution du fichier Python :

python foo_bar.py > file

Ceci écrira tous les résultats imprimés sur stdout depuis le fichier source Python vers le fichier journal.

Ou si vous voulez une journalisation à l'intérieur du script :

import sys

class Logger(object):
    def __init__(self):
        self.terminal = sys.stdout
        self.log = open("logfile.log", "a")

    def write(self, message):
        self.terminal.write(message)
        self.log.write(message)  

    def flush(self):
        # this flush method is needed for python 3 compatibility.
        # this handles the flush command by doing nothing.
        # you might want to specify some extra behavior here.
        pass    

sys.stdout = Logger()

Maintenant, vous pouvez utiliser :

print "Hello"

Ceci va écrire "Hello" à la fois sur stdout et dans le fichier de log.

25voto

user2033758 Points 119

J'ai trouvé le moyen de rediriger la sortie vers la console ainsi que vers un fichier texte simultanément :

te = open('log.txt','w')  # File where you need to keep the logs

class Unbuffered:

   def __init__(self, stream):

       self.stream = stream

   def write(self, data):

       self.stream.write(data)
       self.stream.flush()
       te.write(data)    # Write the data of stdout here to a text file as well

sys.stdout=Unbuffered(sys.stdout)

22voto

Radu Gabriel Points 817

Utiliser le module de journalisation pour déboguer et suivre votre application

Voici comment j'ai réussi à enregistrer dans un fichier et dans la console / stdout.

import logging
logging.basicConfig(level=logging.INFO,
                    format='%(asctime)s - %(levelname)s - %(message)s',
                    filename='logs_file',
                    filemode='w')
# Until here logs only to file: 'logs_file'

# define a new Handler to log to console as well
console = logging.StreamHandler()
# optional, set the logging level
console.setLevel(logging.INFO)
# set a format which is the same for console use
formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
# tell the handler to use this format
console.setFormatter(formatter)
# add the handler to the root logger
logging.getLogger('').addHandler(console)

# Now, we can log to both ti file and console
logging.info('Jackdaws love my big sphinx of quartz.')
logging.info('Hello world')

lisez-le à la source : https://docs.python.org/2/howto/logging-cookbook.html

16voto

Brian Burns Points 398

Sur la base de La réponse d'Amith Koujalgi Voici un module simple que vous pouvez utiliser pour la journalisation.

transcript.py :

"""
Transcript - direct print output to a file, in addition to terminal.

Usage:
    import transcript
    transcript.start('logfile.log')
    print("inside file")
    transcript.stop()
    print("outside file")
"""

import sys

class Transcript(object):

    def __init__(self, filename):
        self.terminal = sys.stdout
        self.logfile = open(filename, "a")

    def write(self, message):
        self.terminal.write(message)
        self.logfile.write(message)

    def flush(self):
        # this flush method is needed for python 3 compatibility.
        # this handles the flush command by doing nothing.
        # you might want to specify some extra behavior here.
        pass

def start(filename):
    """Start transcript, appending print output to given filename"""
    sys.stdout = Transcript(filename)

def stop():
    """Stop transcript and return print functionality to normal"""
    sys.stdout.logfile.close()
    sys.stdout = sys.stdout.terminal

13voto

oha Points 121
from IPython.utils.io import Tee
from contextlib import closing

print('This is not in the output file.')        

with closing(Tee("outputfile.log", "w", channel="stdout")) as outputstream:
    print('This is written to the output file and the console.')
    # raise Exception('The file "outputfile.log" is closed anyway.')
print('This is not written to the output file.')   

# Output on console:
# This is not in the output file.
# This is written to the output file and the console.
# This is not written to the output file.

# Content of file outputfile.txt:
# This is written to the output file and the console.

En Tee classe dans IPython.utils.io fait ce que vous voulez, mais il manque le __enter__ y __exit__ nécessaires pour l'appeler dans le with -déclaration. Ceux-ci sont ajoutés par contextlib.closing .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X