2016-03-20 20 views
5

Tôi muốn sửa đổi cách IPython xử lý các lỗi nhập theo mặc định. Khi tôi thử nghiệm một cái gì đó trong vỏ IPython, tôi thường quên lần đầu tiên nhập os, re hoặc bất cứ điều gì tôi cần. Một vài báo cáo đầu tiên thường làm theo mô hình này:Nhập IPython Ý nghĩa của tôi

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 

Chắc chắn, đó là lỗi của tôi vì có những thói quen xấu và chắc chắn, trong một kịch bản hoặc chương trình thực tế mà làm cho tinh thần, nhưng trong vỏ Tôi thà rằng IPython tuân theo nguyên tắc DWIM DWIM, ít nhất cố gắng để nhập nội dung tôi đang cố gắng sử dụng.

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 

Nếu điều này không thể thực hiện với IPython vani, tôi phải làm gì để thực hiện công việc này? Có phải là wrapper kernel cách dễ nhất tiếp theo không? Hoặc điều này nên được thực hiện trực tiếp trong lõi, với một lệnh ma thuật?

Lưu ý, điều này khác với those kind of question nơi ai đó muốn luôn tải các mô-đun được xác định trước. Tôi không. Vì tôi không biết những gì tôi sẽ làm việc trên, và tôi không muốn tải mọi thứ (và cũng không làm tôi muốn giữ danh sách các mọi thứ cập nhật

Trả lời

10

LƯU Ý:. này bây giờ là được duy trì on Github. Tải phiên bản mới nhất của kịch bản từ đó!

tôi đã phát triển một kịch bản mà liên kết với xử lý thông qua set_custom_exc ngoại lệ IPython của. Nếu có một NameError, nó sử dụng một regex để tìm module bạn cố gắng sử dụng và sau đó sau đó chạy hàm bạn đã cố gọi lại. Đây là mã:

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) 

Bạn có thể thực hiện thao tác này khi bạn khởi động lời nhắc IPython bằng cách lưu nó ở đâu đó và sau đó đặt biến môi trường có tên là PYTHONSTARTUP vào đường dẫn đến tệp này. Bạn đặt biến môi trường khác nhau tùy thuộc vào hệ điều hành của bạn (nhớ để thay đổi đường dẫn):

  • Windows: setx PYTHONSTARTUP C:\startup.py tại dấu nhắc lệnh
  • Mac/Linux (bash): Đặt export PYTHONSTARTUP=$HOME/startup.py vào bạn ~/.bashrc

Dưới đây là bản trình diễn của tập lệnh đang hoạt động:

Demo

+0

_Có nghĩa là, tập lệnh này infi nite-loops trên một số error_ - nếu kết quả nhập khẩu trong NameError và clean-up thường làm cùng một nhập khẩu ... - bạn đã biết những gì sẽ xảy ra. Bạn cần kiểm tra xem mô-đun bạn đang cố nhập có tồn tại không. –

+0

@Rogalski Tôi sẽ làm như thế nào? Tôi biết 'pip' có phương pháp để làm điều này nhưng ai đó có thể đang nhập một thứ gì đó trên máy cục bộ của họ. –

+0

Chạy: 'thử: nhập bất cứ điều gì ngoại trừ ImportError: oops_failed_to_import_handle_it()'? –