2016-03-20 12 views
5

Chcę zmienić sposób, w jaki IPython domyślnie obsługuje błędy importu. Kiedy prototypuję coś w powłoce IPython, zazwyczaj zapominam najpierw importować os, re lub cokolwiek, czego potrzebuję. Pierwszych kilka wypowiedzi często podążać ten wzór:Import IPython Co mam na myśli

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 

Jasne, że to moja wina za to, że złe nawyki i, pewno, w skrypcie lub rzeczywistej program, który ma sens, ale w powłoce Wolałbym że IPython postępuje zgodnie z zasadą DWIM , przez co najmniej próbuje importować to, czego próbuję użyć.

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 

Jeśli nie jest to możliwe z waniliowym ipython, co musiałbym zrobić do tej pracy? Czy wrapper kernel jest najłatwiejszą drogą do przodu? Czy też powinno to zostać zaimplementowane bezpośrednio w rdzeniu za pomocą magicznego polecenia?

Uwaga, różni się to od those kind of question, gdy ktoś chce zawsze ładować wstępnie zdefiniowane moduły. Ja nie. Bo nie wiem, co będę w pracy, a ja nie chcę, aby załadować wszystko (ani nie chcę, aby utrzymać listę wszystko zaktualizowanej

Odpowiedz

10

. UWAGA: To teraz utrzymuje on Github. Pobierz najnowszą wersję skryptu stamtąd!

i stworzył skrypt, który wiąże się z wyłączeniem ipython przeładunku przez set_custom_exc. Jeśli istnieje NameError, używa regex, aby znaleźć to moduł, który próbował użyć, a następnie spróbuj go zaimportować, a następnie uruchomi funkcję, którą próbujesz wywołać ponownie. Oto kod:

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's exception handler 
IPython.get_ipython().set_custom_exc((Exception,), custom_exc) 

Możesz zrobić to automatycznie po uruchomieniu zapytania IPython, zapisując go gdzieś, a następnie ustawiając zmienną środowiskową o nazwie PYTHONSTARTUP na ścieżkę do tego pliku. Ustawić zmienne środowiskowe w różny sposób w zależności od używanego systemu operacyjnego (pamiętaj, aby zmieniać ścieżki):

  • Windows: setx PYTHONSTARTUP C:\startup.py w wierszu polecenia
  • Mac/Linux (bash): Put export PYTHONSTARTUP=$HOME/startup.py do swojej ~/.bashrc

Oto demo skryptu w akcji:

Demo

+0

_Currently, skrypt INFI nite-loops na niektórych błędach_ - jeśli import powoduje NameError i rutynę czyszczenia robi ten sam import ... - już wiesz, co się dzieje. Musisz sprawdzić, czy moduł, który próbujesz zaimportować, istnieje. –

+0

@Rogalski Jak to zrobić? Wiem, że 'pip' ma metody, ale ktoś może importować coś, co jest na ich komputerze lokalnym. –

+0

Uruchom: 'try: importuje cokolwiek z wyjątkiem ImportError: oops_failed_to_import_handle_it()'? –

Powiązane problemy