Make IPython Import What I Mean

I want to change how IPython handles default import errors. When I prototype something in the IPython shell, I usually forget to import os , re or whatever I need first. The first few statements often follow this pattern:

 In [1]: os.path.exists("~/myfile.txt") --------------------------------------------------------------------------- NameError Traceback (most recent call last) <ipython-input-1-0ffb6014a804> in <module>() ----> 1 os.path.exists("~/myfile.txt") NameError: name 'os' is not defined In [2]: import os In [3]: os.path.exists("~/myfile.txt") Out[3]: False 

Of course, my fault is for bad habits and, of course, in a script or a real program that makes sense, but in the shell I would prefer IPython DWIM, at least trying to import what I'm trying to use.

 In [1]: os.path.exists("~/myfile.txt") --------------------------------------------------------------------------- NameError Traceback (most recent call last) <ipython-input-1-0ffb6014a804> in <module>() ----> 1 os.path.exists("~/myfile.txt") NameError: name 'os' is not defined Catching this for you and trying to import "os" … success! Retrying … --------------------------------------------------------------------------- Out[1]: False 

If this is not possible with iphone vanilla, what do I need to do to make this work? Is the wrapping core the easiest way forward? Or should it be implemented directly in the kernel using a magic command?

Please note that this is different from such a question where someone wants to always load predefined modules. I do not. Because I do not know what I will work on, and I do not want to download everything (and I do not want the list of all to be updated.

+5
source share
1 answer

NOTE. Currently supported on Github . Download the latest script from there!

I developed a script that links to IPython exception handling using set_custom_exc . If a NameError exists, it uses a regular expression to find which module you tried to use, and then try to import it. Then it starts the function that you tried to call again. Here is the code:

 import sys, IPython, colorama # <-- colorama must be "pip install"-ed colorama.init() def custom_exc(shell, etype, evalue, tb, tb_offset=None): pre = colorama.Fore.CYAN + colorama.Style.BRIGHT + "AutoImport: " + colorama.Style.NORMAL + colorama.Fore.WHITE if etype == NameError: shell.showtraceback((etype, evalue, tb), tb_offset) # Show the normal traceback import re try: # Get the name of the module you tried to import results = re.match("name '(.*)' is not defined", str(evalue)) name = results.group(1) try: __import__(name) except: print(pre + "{} isn't a module".format(name)) return # Import the module IPython.get_ipython().run_code("import {}".format(name)) print(pre + "Imported referenced module \"{}\", will retry".format(name)) except Exception as e: print(pre + "Attempted to import \"{}\" but an exception occured".format(name)) try: # Run the failed line again res = IPython.get_ipython().run_cell(list(get_ipython().history_manager.get_range())[-1][-1]) except Exception as e: print(pre + "Another exception occured while retrying") shell.showtraceback((type(e), e, None), None) else: shell.showtraceback((etype, evalue, tb), tb_offset=tb_offset) # Bind the function we created to IPython exception handler IPython.get_ipython().set_custom_exc((Exception,), custom_exc) 

You can make this run automatically when you run the IPython prompt, saving it somewhere, and then setting the environment variable named PYTHONSTARTUP to the path to this file. You set environment variables differently depending on your OS (don't forget to change the paths):

  • Windows: setx PYTHONSTARTUP C:\startup.py on the command line
  • Mac / Linux (bash): put export PYTHONSTARTUP=$HOME/startup.py in your ~/.bashrc

Here is a demo of the script in action:

Demo

+10
source

Source: https://habr.com/ru/post/1245414/


All Articles