103 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.

161voto

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.

24voto

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)

17voto

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

14voto

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

9voto

hector garcia Points 99

J'ai imaginé une solution plus simple. Il suffit de définir une fonction qui imprimera vers le fichier ou vers l'écran ou vers les deux. Dans l'exemple ci-dessous, j'autorise l'utilisateur à entrer le nom du fichier de sortie comme argument, mais ce n'est pas obligatoire :

OutputFile= args.Output_File
OF = open(OutputFile, 'w')

def printing(text):
    print text
    if args.Output_File:
        OF.write(text + "\n")

Après cela, tout ce qui est nécessaire pour imprimer une ligne à la fois dans un fichier et/ou à l'écran est : printing(Ligne_à_imprimer)

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