Re: h(re) for help, import re - on NameError
On Fri, Sep 23, 2016 at 4:40 PM, Peter Otten <__pete...@web.de> wrote: > By the way, the current help() already loads a module if you pass its name > as a string: > Yes, which is the basis of my alternate exec trick: exec(tb.tb_frame.f_code, tb.tb_frame.f_globals, {n: n}) Basically it creates a new locals dict that just has (eg) re="re", which allows help(re) to function as help("re"). ChrisA -- https://mail.python.org/mailman/listinfo/python-list
Re: h(re) for help, import re - on NameError
Veek M wrote: > Is there a way to use .pythonrc.py to provide a help function that > autoloads whatever module name is passed like so: By the way, the current help() already loads a module if you pass its name as a string: $ echo 'print("importing foo")' > foo.py $ python3 Python 3.4.3 (default, Sep 14 2016, 12:36:27) [GCC 4.8.4] on linux Type "help", "copyright", "credits" or "license" for more information. >>> help("foo") importing foo Help on module foo: NAME foo [snip] -- https://mail.python.org/mailman/listinfo/python-list
Re: h(re) for help, import re - on NameError
Chris Angelico wrote: > On Thu, Sep 22, 2016 at 8:10 PM, Veek M wrote: >> Is there a way to use .pythonrc.py to provide a help function that >> autoloads whatever module name is passed like so: >> \>>> h(re) >> >> I tried inheriting site._Helper and overriding __init__ and __call__ >> but that didn't work, also I don't know how to deal/trap/catch the >> NameError (no quotes on h(re)) - is there a way to insert a >> try/except block around the >>> prompt? >> >> I hate having to: import whatever every-time i forget. Actually could >> I ditch the () in h(re) and just do: h re - the joy of that :p > > You could use sys.excepthook to catch the NameError. I don't know of a > way to catch the SyntaxError and look at the original text, but with > NameError it's pretty easy: > > def excepthook(t,v,tb): > if t is NameError: > n = v.args[0].split("'")[1] > globals()[n] = __import__(n) > exec(tb.tb_frame.f_code, tb.tb_frame.f_globals) > else: > excepthook.old(t,v,tb) > > import sys > excepthook.old = sys.excepthook > sys.excepthook = excepthook > > Paste that into interactive Python and give it a try. Be aware that > it'll attempt to import *any* dud name, so it'll potentially slow > stuff down any time you typo. Also, it re-executes the current > traceback frame, which may or may not be appropriate; it's fine for > help(re), but not otherwise. > > As an alternative, you could inspect tb.tb_frame.f_code to see if it > matches "help(x)", and if it does, simply re-execute it with the > string form of the name: > > exec(tb.tb_frame.f_code, tb.tb_frame.f_globals, {n: n}) > > This works because help('re') does the same thing as help(re), so by > effectively setting re="re", you gain that functionality without > actually importing into the global namespace. > > Adequately recognizing help(re) without false positives is left as an > exercise for the reader. :) > > ChrisA works great :) - okay so you save and replace the default exception handler for the interpreter. Then when the procedure is called, check to see if type is NameError - if yes, then value contains the error string with module name, so you split and extract module name, and import the module and map it to a name in the global NS and hey presto (run the old code with the modified NS - that's a bit funky)! Regarding fiddling with the code-object, yep, tb.tb_frame.f_code.co_names has a tuple ('h', 're') I suppose that's clean because it's your input after all vs splitting on something system generated (like an error message) works brilliantly - thanks :) -- https://mail.python.org/mailman/listinfo/python-list
Re: h(re) for help, import re - on NameError
On Thu, Sep 22, 2016 at 8:10 PM, Veek M wrote: > Is there a way to use .pythonrc.py to provide a help function that > autoloads whatever module name is passed like so: > \>>> h(re) > > I tried inheriting site._Helper and overriding __init__ and __call__ but > that didn't work, also I don't know how to deal/trap/catch the NameError > (no quotes on h(re)) - is there a way to insert a try/except block > around the >>> prompt? > > I hate having to: import whatever every-time i forget. Actually could I > ditch the () in h(re) and just do: h re - the joy of that :p You could use sys.excepthook to catch the NameError. I don't know of a way to catch the SyntaxError and look at the original text, but with NameError it's pretty easy: def excepthook(t,v,tb): if t is NameError: n = v.args[0].split("'")[1] globals()[n] = __import__(n) exec(tb.tb_frame.f_code, tb.tb_frame.f_globals) else: excepthook.old(t,v,tb) import sys excepthook.old = sys.excepthook sys.excepthook = excepthook Paste that into interactive Python and give it a try. Be aware that it'll attempt to import *any* dud name, so it'll potentially slow stuff down any time you typo. Also, it re-executes the current traceback frame, which may or may not be appropriate; it's fine for help(re), but not otherwise. As an alternative, you could inspect tb.tb_frame.f_code to see if it matches "help(x)", and if it does, simply re-execute it with the string form of the name: exec(tb.tb_frame.f_code, tb.tb_frame.f_globals, {n: n}) This works because help('re') does the same thing as help(re), so by effectively setting re="re", you gain that functionality without actually importing into the global namespace. Adequately recognizing help(re) without false positives is left as an exercise for the reader. :) ChrisA -- https://mail.python.org/mailman/listinfo/python-list