strangethingspy
strangethingspy

Reputation: 246

Python: How to write error in the console in txt file?

I have a python script which every 10 minutes sends me an email with everything written in the console. I am running this with the crontab in my ubuntu 18.04 vps. Sometimes it doesn't send the mail so I assume that when an error happens execution stops but how can I get the errors to be written in a txt file so I can analyze the error ?

Upvotes: 7

Views: 18464

Answers (4)

Mohi Dev
Mohi Dev

Reputation: 3386

You can easily log console error messages into text file with this command

import sys
import logging

# Create a logging instance
logging.basicConfig(level=logging.INFO, format='%(asctime)s %(levelname)s %(message)s',
                    filename='errors.log', filemode='w')


def raise_error():
    a = []
    try:
        # This will raise an IndexError exception
        print(a[1])
    except Exception as e:
        # Log the error to the file
        logging.error('An error occurred:', exc_info=True)


# Call the function that raises an error
raise_error()

Upvotes: 0

Robin maltaros
Robin maltaros

Reputation: 341

To be able to debug and not only know the kind of error that happened, you can also get the error stack using traceback module (usually in the starting package of modules):

import traceback
try:
    my_function()
except Exception as e:
    print(e)
    traceback.print_exc()

And then run your code 'my_code.py' in console usig >>

python my_code.py >> my_prints.txt

All the prints of your code will then be written in this .txt file, including the printed error and its stack. This is very interesting in your case or while running code on a docker if you want to detach yourself from it with ctrl+p+q and still know what is printed.

Upvotes: 1

C.Nivs
C.Nivs

Reputation: 13106

Logging Module

To demonstrate the approach with the logging module, this would be the general approach

import logging

# Create a logging instance
logger = logging.getLogger('my_application')
logger.setLevel(logging.INFO) # you can set this to be DEBUG, INFO, ERROR

# Assign a file-handler to that instance
fh = logging.FileHandler("file_dir.txt")
fh.setLevel(logging.INFO) # again, you can set this differently

# Format your logs (optional)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
fh.setFormatter(formatter) # This will set the format to the file handler

# Add the handler to your logging instance
logger.addHandler(fh)

try:
    raise ValueError("Some error occurred")
except ValueError as e:
    logger.exception(e) # Will send the errors to the file

And if I cat file_dir.txt

2019-03-14 14:52:50,676 - my_application - ERROR - Some error occurred
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
ValueError: Some error occurred

Print to File

As I pointed out in the comments, you could accomplish this with print as well (I'm not sure you will be applauded for it)

# Set your stdout pointer to a file handler
with open('my_errors.txt', 'a') as fh:
    try:
        raise ValueError("Some error occurred")
    except ValueError as e:
        print(e, file=fh)

cat my_errors.txt

Some error occurred

Note that logging.exception includes the traceback in this case, which is one of the many huge benefits of that module

Edit

In the interest of completeness, the traceback module leverages a similar approach as print, where you can supply a file handle:

import traceback
import sys

with open('error.txt', 'a') as fh:
    try:
        raise ValueError("Some error occurred")
    except ValueError as e:
        e_type, e_val, e_tb = sys.exc_info()
        traceback.print_exception(e_type, e_val, e_tb, file=fh)

This will include all of the information you want from logging

Upvotes: 13

Reedinationer
Reedinationer

Reputation: 5774

You can use the logging module as suggested in the comments (possibly superior but outside the scope of my knowledge), or catch the errors with try and except like:

try:
    pass
    #run the code you currently have
except Exception as e: # catch ALLLLLL errors!!!
    print(e) # or more likely you'd want something like "email_to_me(e)"

Although this is generally frowned upon to catch all exceptions, because then should your program fail for whatever reason it will get gobbled up in the except clause so a better approach is to figure out what specific error you are encountering like IndexError and then just catch this specific error like:

try:
    pass
    #run the code you currently have
except IndexError as e: # catch only indexing errors!!!
    print(e) # or more likely you'd want something like "email_to_me(e)"

Upvotes: 3

Related Questions