HOE WORDTERIODIGD STDOUT naar zowel bestand als console met scripting?

Ik wil een Python-script uitvoeren en de uitvoer op een tekstbestand vastleggen en op de console willen laten zien.

Ik wil het opgeven als een eigenschap van het Python-script zelf. Niet om de opdracht te gebruiken echo "hello world" | tee test.txtop opdrachtprompt elke keer.

binnen script dat ik heb geprobeerd:

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

Maar dit toont niet de SUBOUT-uitvoer op het scherm.

Ik heb gehoord van de logging-module, maar ik kon geen geluk krijgen met behulp van die module om de taak te doen.


Antwoord 1, Autoriteit 100%

U kunt Shell-omleiding gebruiken tijdens het uitvoeren van het Python-bestand:

python foo_bar.py > file

Hierdoor wordt alle resultaten opgezet die op stDout worden afgedrukt, van de Python-bron naar het bestand naar de logfile.

of als u inloggen vanaf het 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()

Nu kunt u gebruiken:

print "Hello"

Hiermee wordt “Hallo” op zowel stdout als de logfile.


Antwoord 2, Autoriteit 15%

Ik kreeg de weg om de uit te leiden naar de console en op een tekstbestand zo goed tegelijkertijd:

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)

Antwoord 3, Autoriteit 11%

Gebruik loggenmodule om te debuggen en volg je app

Hier is het inloggen om in te loggen bij het bestand en naar de 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')

Lees het van bron:
https://docs.python.org/2/howto/logging-cookbook.html


Antwoord 4, Autoriteit 9%

Gebaseerd op AMITH KOUJALGI’S ANTWOORD , hier is een eenvoudige module die u kunt gebruiken voor loggen –

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

Antwoord 5, Autoriteit 6%

Ik heb een eenvoudiger oplossing ontworpen. Definieer gewoon een functie die zal afdrukken naar het bestand of op het scherm of aan beide. In het onderstaande voorbeeld sta ik toe dat de gebruiker de uitgaande naam als een argument invoert, maar dat is niet verplicht:

OutputFile= args.Output_File
OF = open(OutputFile, 'w')
def printing(text):
    print text
    if args.Output_File:
        OF.write(text + "\n")

Hierna is alles wat nodig is om een ​​regel te printen, zowel naar het bestand als / of het scherm is:
afdrukken (line_to_be_printed)


Antwoord 6, Autoriteit 5%

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.

De TeeKlasse in IPython.utils.iodoet wat u wilt, maar het mist de __enter__en __exit__-methoden in die nodig zijn om het in de with-statement. Die worden toegevoegd door contextlib.closing.


Antwoord 7, Autoriteit 3%

Hier is een eenvoudige contextbeheerder die naar de console wordt afgedrukt en dezelfde uitvoer op een bestand schrijft. Het schrijft ook uitzonderingen op het bestand.

import traceback
import sys
# Context manager that copies stdout and any exceptions to a log file
class Tee(object):
    def __init__(self, filename):
        self.file = open(filename, 'w')
        self.stdout = sys.stdout
    def __enter__(self):
        sys.stdout = self
    def __exit__(self, exc_type, exc_value, tb):
        sys.stdout = self.stdout
        if exc_type is not None:
            self.file.write(traceback.format_exc())
        self.file.close()
    def write(self, data):
        self.file.write(data)
        self.stdout.write(data)
    def flush(self):
        self.file.flush()
        self.stdout.flush()

Om de contextbeheerder te gebruiken:

print("Print")
with Tee('test.txt'):
    print("Print+Write")
    raise Exception("Test")
print("Print")

Antwoord 8, Autoriteit 3%

Ik heb hier een paar oplossingen geprobeerd en vond niet degene die tegelijkertijd in het bestand en in de console schrijft. Dus hier is wat ik deed (op basis van dit antwoord)

class Logger(object):
    def __init__(self):
        self.terminal = sys.stdout
    def write(self, message):
        with open ("logfile.log", "a", encoding = 'utf-8') as self.log:            
            self.log.write(message)
        self.terminal.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()   

Deze oplossing gebruikt meer rekenkracht, maar slaat op betrouwbare wijze alle gegevens van stdout op in een logbestand en gebruikt minder geheugen. Voor mijn behoeften heb ik ook een tijdstempel toegevoegd aan self.log.write(message). Werkt prima.


Antwoord 9, autoriteit 3%

Deze manier werkte heel goed in mijn situatie. Ik heb zojuist enkele wijzigingen toegevoegd op basis van andere code die in deze thread wordt gepresenteerd.

import sys, os 
orig_stdout = sys.stdout  # capture original state of stdout
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)
#######################################
##  Feel free to use print function  ##
#######################################
print("Here is an Example =)")
#######################################
##  Feel free to use print function  ##
#######################################
# Stop capturing printouts of the application from Windows CMD
sys.stdout = orig_stdout  # put back the original state of stdout
te.flush()  # forces python to write to file
te.close()  # closes the log file
# read all lines at once and capture it to the variable named sys_prints
with open('log.txt', 'r+') as file:
    sys_prints = file.readlines() 
# erase the file contents of log file
open('log.txt', 'w').close()

Antwoord 10

Als u de uitvoer wilt omleiden naar een bestand en een terminal zonder te wijzigen hoe uw Python-script buiten wordt gebruikt, kunt u pty.spawn(itself):

gebruiken

#!/usr/bin/env python
"""Redirect stdout to a file and a terminal inside a script."""
import os
import pty
import sys
def main():
    print('put your code here')
if __name__=="__main__":
    sentinel_option = '--dont-spawn'
    if sentinel_option not in sys.argv:
        # run itself copying output to the log file
        with open('script.log', 'wb') as log_file:
            def read(fd):
                data = os.read(fd, 1024)
                log_file.write(data)
                return data
            argv = [sys.executable] + sys.argv + [sentinel_option]
            rc = pty.spawn(argv, read)
    else:
        sys.argv.remove(sentinel_option)
        rc = main()
    sys.exit(rc)

Als de module ptyniet beschikbaar is (op Windows), kunt u deze vervangen door teed_call()-functiedie draagbaarder is maar gewone leidingen biedt in plaats van een pseudo-terminal — het kan het gedrag van sommige programma’s veranderen.

Het voordeel van op pty.spawnen subprocess.Popengebaseerde oplossingen ten opzichte van het vervangen van sys.stdoutdoor een bestandsachtig object is dat ze kunnen de uitvoer vastleggen op een bestandsdescriptorniveau, bijvoorbeeld als het script andere processen start die ook uitvoer kunnen produceren op stdout/stderr. Zie mijn antwoord op de gerelateerde vraag: Stdout omleiden naar een bestand in Python?


Antwoord 11

Op basis van bewerkt antwoord door Brian Burnsheb ik één lesgroep gemaakt die gemakkelijker te bellen is:

class Logger(object):
    """
    Class to log output of the command line to a log file
    Usage:
    log = Logger('logfile.log')
    print("inside file")
    log.stop()
    print("outside file")
    log.start()
    print("inside again")
    log.stop()
    """
    def __init__(self, filename):
        self.filename = filename
    class Transcript:
        def __init__(self, filename):
            self.terminal = sys.stdout
            self.log = open(filename, "a")
        def __getattr__(self, attr):
            return getattr(self.terminal, attr)
        def write(self, message):
            self.terminal.write(message)
            self.log.write(message)
        def flush(self):
            pass
    def start(self):
        sys.stdout = self.Transcript(self.filename)
    def stop(self):
        sys.stdout.log.close()
        sys.stdout = sys.stdout.terminal

Antwoord 12

Gebaseerd op het antwoord van @arnold Suiza, hier is een functie die u in het begin kunt uitvoeren en daarna wordt alles onmiddellijk afgedrukt naar stDout & amp; Bestand:

def print_to_file(filename):
    orig_stdout = sys.stdout  # capture original state of stdout
    class Unbuffered:
        def __init__(self, filename):
            self.stream = orig_stdout
            self.te = open(filename,'w')  # File where you need to keep the logs
        def write(self, data):
            self.stream.write(data)
            self.stream.flush()
            self.te.write(data)    # Write the data of stdout here to a text file as well
            self.te.flush()
    sys.stdout=Unbuffered(filename)

Voer nu gewoon in print_to_file('log.txt')op het programma Start en je bent klaar om te gaan!


Antwoord 13

Ik heb dit geprobeerd:

"""
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, sys.stderr
        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
    sys.stderr = sys.stderr.terminal

Antwoord 14

U kunt de uitvoer doorverwijzen naar een bestand door & GT; & GT; Python met de “Chevron” -syntaxis van Print Rint zoals aangegeven in de docs

Laat zien,

fp=open('test.log','a')   # take file  object reference 
print >> fp , "hello world"            #use file object with in print statement.
print >> fp , "every thing will redirect to file "
fp.close()    #close the file 

Afrekenen De bestandstest. Log U hebt de gegevens
En om op de console af te drukken, gebruik dan PLAIND PRINT Verklaring.

Other episodes