[HN Gopher] Implementing Rust's dbg! in Python
       ___________________________________________________________________
        
       Implementing Rust's dbg! in Python
        
       Author : soopurman
       Score  : 89 points
       Date   : 2020-12-11 14:47 UTC (8 hours ago)
        
 (HTM) web link (rtpg.co)
 (TXT) w3m dump (rtpg.co)
        
       | mmastrac wrote:
       | Title should definitely have `dbg!` in it rather than "Dbg"
        
         | dang wrote:
         | Fixed now.
        
         | codetrotter wrote:
         | Probably was submitted with the correct title and then
         | rewritten by the HN title modification ruleset.
         | 
         | I think submitters are able to correct the title for a while
         | and that when they do it might(?) override some or all of the
         | rules in the filter. But the time window for doing so has
         | probably been passed now.
         | 
         | Mods could still change the title though.
         | 
         | Either to the original:
         | 
         | Implementing Rust's dbg! in Python
         | 
         | Or if they want to help out those unfamiliar with Rust syntax
         | they might make the title be:
         | 
         | Implementing Rust's dbg! macro in Python
         | 
         | And if they are opposed to use the bang even in this context it
         | would then be fine IMO to either preferably set the title to:
         | 
         | Implementing Rust's dbg macro in Python
         | 
         | Or less preferably to set the title to:
         | 
         | Implementing Rust's debug macro in Python
        
           | penagwin wrote:
           | @dang we are in great need
        
       | orf wrote:
       | Python now as a semi-shortcut for this (just add = to the end of
       | any f-string expression):
       | 
       | In [8]: print(f'{foo.bar[1]=}') foo.bar[1]='2'
       | 
       | You can do more complex expressions:
       | 
       | In [9]: f'{1+1=}' Out[9]: '1+1=2'
       | 
       | It's not quite as fluid as dbg!(), but it's nice.
        
         | gknoy wrote:
         | For anyone else wondering why we get a syntax error, this seems
         | to be new in 3.8. :)
        
           | giancarlostoro wrote:
           | So anyone using Ubuntu or Debian, maybe for the next major
           | release you can try it out. I love Debian but I hate that I
           | cant just install the latest of Python system wide without
           | potentially breaking system level scripts.
        
             | Drdrdrq wrote:
             | Just use pyenv (careful with spelling), then you can use
             | any version you like.
        
       | tpoacher wrote:
       | I dont get, isn't this just grabbing the filename (which has a
       | built-in double underscore file variable), and the line number
       | (e.g. https://code.activestate.com/recipes/145297-grabbing-the-
       | cur...)
       | 
       | not to mention you can run via pdb and display or stop at points
       | of interest.
       | 
       | what am I missing?
        
         | CJefferson wrote:
         | dbg! also prints out both the value of the expression, and the
         | expression itself, so dbg!(x+y) prints 'x+y=3'
        
       | okl wrote:
       | Here's a lib with similar functionality:
       | https://github.com/alexmojaki/snoop
        
       | jlmorton wrote:
       | While I realize we don't always have a logger wired up, it's also
       | easy to implement this in standard logging.
       | 
       | %(filename_lineno)s will give you the filename and line.
        
       | [deleted]
        
       | JackC wrote:
       | Rust's dbg! is one of those ideas that felt obvious and beautiful
       | once I saw it.
       | 
       | Apparently it's inspired by Haskell.[0] I'd love to see it
       | officially picked up in other languages.
       | 
       | [0] https://rust-lang.github.io/rfcs/2361-dbg-
       | macro.html#prior-a...
        
         | lock-free wrote:
         | I've been using it in C/C++ projects going back at least 15
         | years, I thought it was commonplace for every language
        
           | dagmx wrote:
           | Do you have an example of using it in C or C++?
        
             | lock-free wrote:
             | https://stackoverflow.com/questions/1644868/define-macro-
             | for...
        
               | dagmx wrote:
               | Like Steve said, what you're talking about is quite a bit
               | different than what the rust dbg macro does.
        
               | CyberDildonics wrote:
               | It isn't really that different, it can just be used in
               | inline expressions. Having the macro do nothing or just
               | evaluating to the expression in debug mode is trivial,
               | since a debug symbol would be defined.
        
               | steveklabnik wrote:
               | There's a few significant differences here. This is a
               | printf that only happens in debug mode; dbg is something
               | that takes an expression, returns that expression, and
               | will print out its filename, line number, and a pretty-
               | printed version of the value.
               | 
               | For an example of how this plays out, I had some code:
               | let x = y + z;
               | 
               | I wasn't sure what y was, so I was able to
               | let x = dbg!(y) + z;
               | 
               | this is _much_ easier to insert into (and remove from)
               | existing code. Plus, you don 't need to write the
               | formatting code.
               | 
               | Basically, what you posted is in the same _genre_ of
               | thing, but is very different in a lot of meaningful ways.
        
               | digikata wrote:
               | You can use dbg inline within an expression!? How did I
               | miss that?
        
               | steveklabnik wrote:
               | You can even use it inside itself. I've written
               | let c = dbg!(dbg!(a) + dbg!(b));
               | 
               | one time...
        
               | jrimbault wrote:
               | I've written a 3 nested dbg! line for a complex boolean
               | expression... I should have just written a truth table...
        
               | brodie wrote:
               | Maybe you should write a truth table/source code macro!
        
               | CJefferson wrote:
               | After I saw this in Rust, I had to implement it in C++:
               | #include <iostream>         #include <string>
               | template<typename T>         T print_dbg(T val,
               | std::string exp, std::string file, int line)          {
               | std::cerr << exp << " = " << val << " @ " << file << ":"
               | << line << "\n";             return val;         }
               | #define dbg(x) print_dbg(x,#x,__FILE__,__LINE__)
        
       | aftbit wrote:
       | Typo in your first eval example:                   >>> foo = {
       | ...     'bar': 3         ... }         >>>
       | print(eval("foo['bar'[]"))         Traceback (most recent call
       | last):           File "<stdin>", line 1, in <module>
       | File "<string>", line 1             foo['bar'[]
       | ^         SyntaxError: unexpected EOF while parsing
        
         | __lazybyte wrote:
         | I think that's the extra opening square bracket.
         | 
         | Should be: print(eval("foo['bar']"))
        
       | azkae wrote:
       | I use icecream [1] for the same purpose while debugging. It's
       | really handy.
       | 
       | [1] https://github.com/gruns/icecream
        
         | memco wrote:
         | Thanks for sharing! I like that ic includes a hook for logging,
         | which I think is an advantage over calling print directly. I
         | realize for a lot of examples, they're quick and dirty but I
         | almost always end up setting up a logger with an stderr or
         | stdout handler so that other handlers can also send it to a
         | file if desired. This makes it easier to run these in
         | production on daemons and such where your code might not have
         | an stdout to print to.
        
       | da39a3ee wrote:
       | The one thing I wasn't sure that I liked with rust's dbg! is that
       | I was typically passing the argument by value, but that sometimes
       | works and sometimes fails the borrow checker. But now reading
       | https://github.com/rust-lang/rust/issues/59943 I see that this is
       | a feature -- I hadn't been taking advantage of the fact that you
       | can use dbg! inline; I'd just been adding extra dbg!(foo) lines
       | to the code. So I should probably (a) pass by reference always
       | and (b) look our for where inline dbg! might be useful (probably
       | lots).
        
       | drewm1980 wrote:
       | Might be worth mentioning that you do not have to resort to
       | printf debugging in Rust or python; both languages have good ide
       | debugger support. I use python and rust together professionally.
        
         | brundolf wrote:
         | For something quick, it's often more ergonomic to just print a
         | thing out than step through. Also, most debuggers also won't be
         | very helpful for embedded expressions; you have to break it out
         | into a local variable.
        
         | damnyou wrote:
         | printf debugging (i.e. listing code execution traces) is better
         | than a breakpoint-based debugger in most situations, in my
         | opinion.
        
           | breuleux wrote:
           | For what it's worth, I made a Python package that lets you
           | combine both approaches:
           | https://github.com/breuleux/breakword. You run your program
           | once to print out what's going on, but it also displays a
           | unique word next to each line and on a second run you can set
           | a breakpoint at any of these words to investigate deeper.
           | It's pretty handy when you spot an issue at the hundredth
           | invocation of some function deep in the program's execution.
        
         | colejohnson66 wrote:
         | Would this make sense in a logging situation?
        
       | [deleted]
        
       | The_rationalist wrote:
       | I created a similar macro in C++, it had the ability to show the
       | function name in addition to the file name
        
         | db48x wrote:
         | But did it return the value being printed? That's the thing
         | most implementations miss.
        
           | The_rationalist wrote:
           | Oh never thought about that use case but I imagine it would
           | have been simple to add
        
       ___________________________________________________________________
       (page generated 2020-12-11 23:01 UTC)