logging_setup.pyjust for ease of use. I'm just sharing it if anyone wants to.
This has a few defaults:
- prints to a file (.txt b/c Pythonista doesn't open .log by default)
- Note: if used in different scripts, the 'name' arg is important for logging to different files.
- mode is set to overwrite (you can set it with keyword arg)
- format looks like this: "DEBUG: this is a message." (can change with
A few benefits:
- can have the log file in a tab in the editor
- can use the 'Find' in editor to search the log
- no console take-over when running your script
import logging import logging_setup log = logging_setup.logging_setup('my_log') #use a unique name log.debug('a message for the log') log.error('oh no.') log.warning('oh no.') log.critical('call 911... or omz') log.info('well now it seems you have some mighty fine logging going on.') logging.shutdown() #necessary at the end of the script running
I did test this with using it in a few different files at the same time. I didn't think it was going to work because of name spaces (ex: if you use
login two files and have imported one file into the other) - but it seems to work fine. One very important thing: if you do not use
logging.shutdown()it will not work properly (seems that logs are carried over from before).
Comments on the gist https://gist.github.com/danrcook/369bf95d2a4d857f00fc84a0c1f261a8
@ccc yeah I havent really ventured out into making a project that incorporates more than one file yet. But of course when I do (and from now on) I think this sort of thing will be very nice. It's much better than cluttering up the console!!
@cook, just made a new post to that story you referenced. I think it's worth pointing though. Maybe everyone knows about that param, seen it a million times, maybe just not used it or thought about it.
In my example below, I actually open a file. And maybe there is another file like object that is just a null device. I just didn't find it yet 😁
Hmmm, I just come across something. It's sort of there, but not 100%.
In py3 print has a file param.
So you can do the below. It's still ok for a quick and dirty.
# opening here with 'a', could use 'w' log = open('my_print_code.txt', 'a') pfile = log # does not print to console, prints to the log file (Just text) for i in range(0, 100): print( i, file = pfile) # this prints to the console pfile = None for i in range(0, 10): print( i, file = pfile) print('finshed') # file param not used, goes to sys.stdout log.close()
Of course under Python 3 you can also just say
def print(*args, **kwargs): pass
to hide the built-in
to get it back. Under Python 2 this doesn't work, because
@dgelessus , True 😁 But is not a toggle switch from what I understand. Maybe it is.
But I can still see your code would let me simplify my idea. Override the print (as you are doing) statement and use a global to redirect the output inside the overwritten print function. Then no need to provide the file param each time to the real print statements.
If you reread the github thread, i provided a switch option -- adding a console.enabled which you can use wherever.
That might be useful for running someone else's chatty code, where they used print, but for your own code, logging really is the way to go, where the "switch" is the logging level... Here is a console version of logging.
import logging,sys # create logger logger = logging.getLogger('pythonista') # pythonista does not clear logging handlers. # so, we might have one setup already if not logger.hasHandlers(): # create console handler with a higher log level ch = logging.StreamHandler(stream=sys.stdout) # create formatter and add it to the handlers formatter = logging.Formatter('%(message)s') ch.setFormatter(formatter) # add the handlers to the logger logger.addHandler(ch) logger.setLevel(logging.INFO) logger.debug('debug') logger.warning('warning') logger.info('info')
@JonB , yeah yeah yeah.....
But I seen the comment monkey patch, my brain switched off. I don't know what a monkey patch is. But is sounds not good.
But ok,,it seems like monkey patch refers to overriding a built in function or maybe data type etc... But it sounds notorious than that.
Honestly, for lay people these words are scary. Sounds like some super black magic , then you just skip it. Now, I actually read below the money patch statement I can see you did give a more detailed example of the same thing.
Maybe monkey patch has more far reaching concepts than what. I just sort of figured out. But have to look it up I guess.
Today afternoon, 1:51am here already.
By the way, you should add a check for hasHandler before adding a handler. Pythonista's global clearing code does not stop or clear out loggers, so the old logger will still have its handlers. (in the past I wanted to have a logger that logged to a BytesIO, so I could control when log entries were dumped to the screen, and this caused me lots of trouble)
This seems to prevent the need for shutdown()... i think
@ccc , thanks. 0k, it's not as scary as it sounds. I know it may seem like a simple think not to know about, but there are a lot of things to know about. Whilst it's good to know about, probably better I don't screw with it, at least for now anyway as @JonB points out. I can get into trouble many other ways 😬😱
But I love the quote on the wiki page you linked to.
'If it walks like a duck and talks like a duck, it’s a duck, right? So if this duck is not giving you the noise that you want, you’ve got to just punch that duck until it returns what you expect. "