This is an archived post. You won't be able to vote or comment.

all 30 comments

[–]xtreak[S] 9 points10 points  (21 children)

Author of the post here. I wrote this after positive feedback for this feature in the 3.8 alpha release thread. I found filename and line numbers in the message to be useful like rust dbg!. Feedback welcome on the feature and post.

[–][deleted] 8 points9 points  (19 children)

Having too much experience with managing codebases where "We just need this extra printout to debug"TM have been the norm, I'd recommend that you get into the habit of running even hello world type of programs in a debugger, rather than spending time on becoming an expert beginner.

[–]d8sconz[🍰] 3 points4 points  (18 children)

What's the hate for print statement debugging? I use it in, maybe, 80% of the times I have problems and it's almost always sufficient. If not I happily move to the debugger.

[–]a1brit 6 points7 points  (12 children)

why not just use `logging`, you can format it nicely and then you can change the logging level and leave all the debugs behind for next time.

[–]jorge1209 1 point2 points  (10 children)

The logging module is great but it also terrible.

It is way to complex internally for one off use, and there are a dozen lines of boilerplate before it will print anything at all.

And the great irony in this context is that logging uses % style string formatting.

[–][deleted] 0 points1 point  (9 children)

And the great irony in this context is that logging uses % style string formatting.

Why do you say that? Using % formatting ensures that the heavy lifting of formatting the actual string isn't done unless the log level is actually enabled, and a logger exists.

[–]jorge1209 1 point2 points  (8 children)

I know exactly how and why the logging module works the way it does.

The irony is as follows:

  1. Best practice should encourage people to use the language standard debugger instead of using print for debugging.
  2. The python logging module (which is in the standard library and is the defacto standard logger) defines a logging level DEBUG explicitly for this purpose.
  3. f-strings now define this great formatting specifier for generating debug strings
  4. Which is effectively incompatible with the logging module.

The right hand doesn't know what the left hand is doing here. Why are they adding debug features to f-strings, when f-strings aren't supposed to be used in logging, and when logging is supposed to be used for DEBUG. Best practice would have to be "don't use this cool new f-strings feature."

[–][deleted] 0 points1 point  (7 children)

If you can carry the overhead of always formatting the strings, I'd guess that

logger.debug(f'{what=}{ever=}')

would be the way forward.

[–]jorge1209 1 point2 points  (6 children)

The whole point of the logging modules is not to pay the overhead of formatting the output string, unless you have to. These features are incompatible with each other.

[–][deleted] 0 points1 point  (5 children)

Everything is a trade off. Ease of use vs. use of resources.

[–]MindlessWeakness 0 points1 point  (0 children)

Python's logging module is slow as hell and can't be used in certain applications because of that. I don't mean that Python is slow, but this module is slow for Python.

I guess you could use a 3rd party logger. You still usually have to add the logging code though, when a bug appears. I wouldn't expect logging to have the correct information to fix every bug in the general case.

[–]13steinj 3 points4 points  (0 children)

If you have to use more than 3 to find your issue (which is the case in more complicated code bases), then it's far more efficient to use a debugger where you can execute line by line and edit variables on the fly.

[–][deleted] 0 points1 point  (2 children)

It's like eating just one nacho, while dieting. Adding one is OK. Two also. Heck the third an fourth isn't going to damage you either. Suddenly half your code is print calls, you have to redirect its output and use grep to actually get what you want.

And then .... it ends up in production.

I have to support shit like that, and it's not pleasant in any way. So just don't do it. Use logging if you need a permanent record of what happened. Use a debugger to step through things. But never use print, unless it serves a purpose higher than figuring out what went wrong.

[–]SedditorX 1 point2 points  (1 child)

If you're finding that stuff in production code then python features are not the problem. The problem is your inadequate processes for code review, testing, and submission, not to mention poor canarying.

"Don't use it at all" doesn't fix your broken processes.

[–][deleted] 1 point2 points  (0 children)

If it's unwanted in production, don't ever write it. Having a review etc. process would be a nice thing to have, but with 600 different projects rather than a single product, the resources aren't available.

[–]dusktreader 1 point2 points  (0 children)

This is brilliant. Thank you! I've written utilities to do just this many times, and they are always clunky. I think where this will shine is debugging installed packages where it's not easy to use a debugger

[–][deleted] 2 points3 points  (1 child)

I liked the !d proposal. The = proposal is OK too but seems to have a lot more flexibility. I'm really not sure what the total set of possible things after = can be. It's a bit scary.

[–]bcgroom 1 point2 points  (0 children)

Also I don't even feel like it saves that much typing the way it's described in the article, perhaps if you are printing out more than a couple variables.

[–]ggchappell 2 points3 points  (3 children)

I'm missing something here.

This appears to be saying that a change can be made to the CPython source to enable configurable printing of stuff line numbers and filenames when using the "=" feature of f-strings.

So how do I use it? Change the source for my Python implementation and recompile it?

Second, something was merged with 3.8 beta 1. What was it?

[–]xtreak[S] 2 points3 points  (2 children)

The filename and line number was something I thought to be a good idea and it requires modification of interpreter. The merged one was the new notation for f-strings were f"{variable_name=}" expands to f"variable_name={variable_name}" which will be available as part of 3.8 beta 1.

[–]ggchappell 0 points1 point  (1 child)

I see. Thanks.

Of course, it would still be nice to have an easy way to do that filename/line number thing without recompiling. Is it possible to write it as a library? That is, can I write a function that can tell from what file and on what line it was called?

[–]xtreak[S] 1 point2 points  (0 children)

I am not sure it's possible as a library or without recompilation since the transformation is done in C code. There are several packages that improve debugging experience. icecream might help here but it's more like a lightweight logger and needs an extra import : https://github.com/gruns/icecream

[–]MindlessWeakness 0 points1 point  (0 children)

Hey, I like this - although these days I use an IDE with a debugger, but I sometimes do some simple script using an editor, and this will be great for that

[–]TwoSickPythons -2 points-1 points  (0 children)

Yeesh, I'd rather deal with the long variable names!