Following up on some discussions in the chat from last InSession, I’ve built our own quick and dirty version of of the debug() statement that also has a global flag for disabling all print statements. I think this could be something valuable in TouchDesigner natively. Something like a tdu.print() function that works exactly like print() from Python but with the extra options maybe in the Preferences to “Disable printing” and “Display print path” to get the benefits of both debug() and globally disabling print commands.
In my projects I use the built-in logging module in Python for this goal. It already has 6 logging levels which you can use:
This makes it easy to switch off any debug output on production machines, and maybe only show critical there or nothing.
See a basic tutorial here:
Thanks guys, been hearing a lot about this subject lately. I’ll start the process rolling!
@nettoyeur I think that’s fine for us, because I think most of us more advanced folks have made workarounds or dived into Python more seriously, but for new folks it feels like lately I hear a lot of “how do I search for print statements that I forgot where I put them in my project?” I don’t think we have to re-invent the wheel here by anymeans, so maybe something like a tdu.print() wrapper for the built in Python logging could work. But I can imagine if we pointed new folks to go learn how to use Python logging library and it’s different levels of logs, eyes might glaze over haha.
What I’m thinking is to build a wrapper around the logger. Introduce a new “log” command that replaces “debug”. I would like the simplicity of access that @elburz is suggesting but with the robust possibilities of @nettoyeur’s suggestion. Would be nice to create a standardized solution that most people could use out of the box.
Log’s default behavior would be just like “debug” but would actually be printing a log statement at the debug priority level. But you could also specify a different level with an argument: log(‘my log’, level=‘Warning’). You could then have access to which levels print to the textport and also which levels print to a log file.
How does that sound?
Now we’re cooking with gas! I think that’d be pretty dope. I’d make a YouTube video about that on launch! People would love that and would be really easy for new folks.
+1 to your idea @Ivan !
I think that would combine the best of both worlds @Ivan !
a lot of people don’t use the standard
debug()command because it fills the console with text like:
(Debug: line 54 of /project1/text1)which makes it harder to see the output you need.
But because they use the
print()command instead, they loose track of where in their project they have placed all their
So I would suggest a simple overall toggle in TD to enable/disable file / function / line numbers. You you can do this by setting the LogRecord attributes in the formatter objects
But if you are going to build something in TD where such formatting options are set overall (in the GUI?) , it would be best if we could override these options in Python itself. That way both Python beginners and experts can work together with the same “log” command in their codebase.
So for instance if I would write something like this in my extension
log.formatter=('%(asctime)s - %(module)s.%(funcName)s (line %(lineno)d) - %(message)s', datefmt='%d-%b-%y %H:%M:%S')
and this in a method inside MyExt:
def loadFiles(self): #load files log('Files are loaded')
I would expect to always get
26-Aug-20 20:53:19 - MyExt.loadFiles(line 54) - Files are loaded
independent of what overall options are set in TD
I was about to integrate a logging module so thanks to everyone else for doing the work. The only things I would add are:
- Ensure that logs below the desired levels are ignored as soon as possible to not waste cycles (I like to do a lot of very verbose logging in a dev environment)
- Add the ability for structured logging, which especially helps in a distributed environment and with log aggregation tools.
Or maybe just wrap an implementation of https://www.structlog.org?
And I guess now that I’ve brought up the concept of a dev environment, it would be nice to have a way to choose overall config based on environment variables so this could all be configured at runtime without changing the network. Or maybe this already exists? Sorry for the scope creep!
Just a heads up that this project didn’t make it to the high priority list, but I will definitely come back to this thread and take in all the suggestions when it bubbles up there! Feel free to keep throwing out ideas. I’ll post again when I start on this.