[IPython-dev] Changing functions in a running program?

Wes Turner wes.turner at gmail.com
Sat Jan 12 21:42:18 EST 2019


In searching for a solution, I found your question here:
https://stackoverflow.com/questions/54153888/how-to-update-nested-functions-in-ipdb

It's funny, I've been coding in Python for very many years and I've never
encountered this need.
With TDD, you basically never do this: you write a different function and
test that;
if it needs to be parametrized ("dependency injection"),
you just pass a function reference as an argument.
(If the code is designed to be changed at runtime (polymorphic),
that should be part of the callable parameter spec.)

But that doesn't help with this simple example
(or probably the code you're actually working with).

IIUC, this is ocurring because
print_name in the main() function is already bound to the previous instance.

in order to change that reference,
we need to update __self__/__module__.print_name.
Maybe coincidentally I also have no idea how to do this without importing
inspect?
If it was a class method, a simple assignment would accomplish your
objective.

This works:

ipdb> !import inspect; inspect.currentframe().f_globals['print_name'] =
lambda: print("Bob")

But there may be a simpler solution?


On Sat, Jan 12, 2019 at 8:57 PM Andreas Yankopolus <andreas at yank.to> wrote:

> Wes,
>
>
> https://stackoverflow.com/questions/48112226/update-a-function-during-debugging-pdb-or-ipdb
> - Does this work from just a plain ipdb shell (when not sending the
> new function definition from emacs)?
>
>
> This is getting close, but updating the function as proposed doesn’t work.
> Using the example code from my previous post:
>
> *ayank at snorri*:*~/Documents*$ ./foo.py
> In main.
> > /home/ayank/Documents/foo.py(16)main()
>      14     print ("In main.")
>      15     Pdb().set_trace()
> ---> 16     name()
>      17
>      18 if __name__ == "__main__":
>
> ipdb> print_name()
> Alice
> ipdb> name()
> Alice
> ipdb> !def print_name(): print ("Bob")
> ipdb> print_name()
> Bob
> ipdb> name()
> Alice
>
> We can see that the function is updated, but functions that call it do not
> get updated to use the new definition. Any idea what’s going on here?
>
> This kind of thing is no problem in Lisp, but its macro facility means
> that support for changing code at runtime is baked deep into the language.
> Perhaps there’s something missed in the IPython REPL?
>
> Thanks,
>
> Andreas
>
>
>
On Sat, Jan 12, 2019 at 8:37 PM Wes Turner <wes.turner at gmail.com> wrote:

> https://en.wikipedia.org/wiki/Monkey_patch#Pitfalls
>
> https://pypi.org/search/?q=monkeypatch
>
>
> https://docs.pytest.org/en/latest/monkeypatch.html#monkeypatching-mocking-modules-and-environments
>
>
> https://stackoverflow.com/questions/48112226/update-a-function-during-debugging-pdb-or-ipdb
> - Does this work from just a plain ipdb shell (when not sending the new
> function definition from emacs)?
>
>
> On Sat, Jan 12, 2019 at 6:11 PM Andreas Yankopolus <andreas at yank.to>
> wrote:
>
>> Is it possible to run a program to a breakpoint in IPython and then
>> change functions within that program? This would be for interactively
>> experimenting with program logic without having to restart the program from
>> scratch. I’m running IPython3 from Emacs using Elpy for interacting with
>> the IPython3 process.
>>
>> Consider foo.py as follows:
>>
>> #!/usr/bin/env ipython3
>>
>> import sys
>> from IPython.core.debugger import Pdb
>>
>>
>> def print_name():
>>     print ("Alice")
>>
>> def name():
>>     print_name()
>>
>> def main(argv):
>>     print ("In main.")
>>     Pdb().set_trace()
>>     name()
>>
>> if __name__ == "__main__":
>>     main(sys.argv[1:])
>>
>> Running it gives me:
>>
>> *ayank at snorri*:*~/Documents*$ ./foo.py
>> In main.
>> > /home/ayank/Documents/foo.py(16)main()
>>      14     print ("In main.")
>>      15     Pdb().set_trace()
>> ---> 16     name()
>>      17
>>      18 if __name__ == "__main__":
>>
>>
>> ipdb>
>>
>> I now want to change the definition of print_name() to print “Bob”
>> instead of “Alice”. I can make this change in Emacs, send the new function
>> to IPython with C-c C-y f, but when I then type name(), I get “Alice”.
>> The reference to print_name() in name() is not getting updated to point
>> to the new definition of print_name(). Likely I’m going about this
>> process incorrectly, as I can make these kind of changes at an IPython3
>> prompt but not at an ipdb one.
>>
>> Thanks,
>>
>> Andreas
>> _______________________________________________
>> IPython-dev mailing list
>> IPython-dev at python.org
>> https://mail.python.org/mailman/listinfo/ipython-dev
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/ipython-dev/attachments/20190112/842018b0/attachment-0001.html>


More information about the IPython-dev mailing list