Tải lại các mô hình con trong IPython


363

Hiện tại tôi đang làm việc trên một dự án python có chứa các mô đun con và sử dụng numpy / scipy. Ipython được sử dụng như bảng điều khiển tương tác. Thật không may, tôi không hài lòng lắm với quy trình làm việc mà tôi đang sử dụng ngay bây giờ, tôi sẽ đánh giá cao một số lời khuyên.

Trong IPython, khung được tải đơn giản import lệnh . Tuy nhiên, thường là cần thiết để thay đổi mã trong một trong các mô hình con của khung. Tại thời điểm này, một mô hình đã được tải và tôi sử dụng IPython để tương tác với nó.

Bây giờ, khung chứa nhiều mô-đun phụ thuộc lẫn nhau, tức là khi khung được tải ban đầu, mô-đun chính đang nhập và định cấu hình các mô hình con. Các thay đổi đối với mã chỉ được thực hiện nếu mô-đun được tải lại bằng cách sử dụng reload(main_mod.sub_mod). Điều này là cồng kềnh vì tôi cần tải lại tất cả các mô-đun đã thay đổi bằng cách sử dụng đường dẫn đầy đủ. Sẽ rất thuận tiện nếu reload(main_module)cũng tải lại tất cả các mô-đun phụ, nhưng không tải lại numpy / scipy ..


Bạn có quan tâm để giải thích nhiều hơn về However, it is often necessary to change code in one of the submodules of the framework.Vì vậy, tại sao necessary to change codekhông? Cảm ơn
ăn

16
@eat: Khung liên tục được phát triển, do đó, có những thay đổi liên tục đối với cơ sở mã.
Alain

Câu trả lời:


531

IPython đi kèm với một số phép thuật tải lại tự động :

%load_ext autoreload
%autoreload 2

Nó sẽ tải lại tất cả các mô-đun thay đổi mỗi lần trước khi thực hiện một dòng mới. Cách làm việc này hơi khác so với dreload. Một số hãy cẩn thận áp dụng, gõ %autoreload?để xem những gì có thể đi sai.


Nếu bạn muốn luôn bật cài đặt này, hãy sửa đổi tệp cấu hình IPython của bạn ~/.ipython/profile_default/ipython_config.py[1] và nối thêm:

c.InteractiveShellApp.extensions = ['autoreload']     
c.InteractiveShellApp.exec_lines = ['%autoreload 2']

Tín dụng cho @Kos thông qua một bình luận dưới đây.

[1] Nếu bạn không có tệp ~/.ipython/profile_default/ipython_config.py, bạn cần gọi ipython profile createtrước. Hoặc các tập tin có thể được đặt tại $IPYTHONDIR.


63
Tôi có c.InteractiveShellApp.extensions = ['autoreload']c.InteractiveShellApp.exec_lines = ['%autoreload 2']trong tôi ~/.ipython/profile_default/ipython_config.py.
Kos

4
Đó có thể là một hit hiệu suất, tuy nhiên, vì vậy sử dụng một cách thận trọng.
asmeker

3
Việc tải lại chỉ được thực hiện khi bạn nhấn Enter trong Ipython và thường không đáng chú ý.
pv.

3
Điều này hoạt động khá tốt khi gỡ lỗi các gói, vì vậy mục đích của dreload là gì, có vẻ như dreload quá xâm lấn và in lỗi khi một số gói như matplotlib được tải.
bảnh bao

3
Nếu bạn sử dụng phương thức @Kos, hãy đảm bảo c được xác định: c = get_config ()
Tickon

27

Trong IPython 0.12 (và có thể sớm hơn), bạn có thể sử dụng:

%load_ext autoreload
%autoreload 2

Điều này về cơ bản giống như câu trả lời của pv. , ngoại trừ việc tiện ích mở rộng đã được đổi tên và hiện được tải bằng cách sử dụng %load_ext.


20

Vì một số lý do, dường như không %autoreload, cũng không dreloadhoạt động cho tình huống khi bạn nhập mã từ sổ này sang sổ khác . Chỉ Python đơn giản reloadhoạt động:

reload(module)

Dựa trên [1] .


10
Trong Python 3.4+, bạn có thể tìm thấy tải lại trong mô-đun importlib. Xem câu hỏi này .
Praveen

1
Phương pháp này hoạt động khi thêm một phương thức thể hiện, không giống như %autoreloadkỹ thuật. Có một báo cáo lỗi mở để thêm hỗ trợ cho %autoreloadviệc này. .
ijoseph

18

IPython cung cấp dreload()để tải lại đệ quy tất cả các mô hình con. Cá nhân, tôi thích sử dụng %run()lệnh ma thuật (mặc dù nó không thực hiện tải lại sâu, như được chỉ ra bởi John Salvatier trong các bình luận).


11
Tôi nghĩ rằng (thật không may)% run script.txt chỉ tải lại tập lệnh bạn đang gọi chứ không phải các gói mà nó nhập. Nếu bạn đang cố gắng gỡ lỗi một gói bạn đang xây dựng, đây có thể là một nỗi đau.
John Salvatier

2
Lưu ý dreloadđã được thay thế trong IPython gần đây (ví dụ IPython 6.0) bằng cách tải sâu .
dan mackinlay

8

Mô-đun có tên importlibcho phép truy cập để nhập nội bộ. Đặc biệt, nó cung cấp chức năng importlib.reload():

import importlib
importlib.reload(my_module)

Trái ngược với %autoreload,importlib.reload() cũng đặt lại các biến toàn cục được đặt trong mô-đun. Trong hầu hết các trường hợp, đó là những gì bạn muốn.

importlibchỉ khả dụng kể từ Python 3.1. Đối với phiên bản cũ hơn, bạn phải sử dụng mô-đun imp.


giải pháp duy nhất hiệu quả với tôi
gustavz

5

http://shawnleezx.github.io/blog/2015/08/03/some-notes-on-ipython-startup-script/

Để tránh gõ các hàm ma thuật đó nhiều lần, chúng có thể được đặt trong tập lệnh khởi động ipython (Đặt tên cho hậu tố .py dưới .ipython / profile_default / startup. Tất cả các tập lệnh python trong thư mục đó sẽ được tải theo thứ tự từ vựng), mà trông giống như sau:

from IPython import get_ipython
ipython = get_ipython()

ipython.magic("pylab")
ipython.magic("load_ext autoreload")
ipython.magic("autoreload 2")

Điều này cũng có vẻ hiệu quả nếu bạn đang chạy tập lệnh của mình với ví dụ %run script.pytừ IPLthon REPL
Patrick Sanan

3

Còn cái này thì sao:

import inspect

# needs to be primed with an empty set for loaded
def recursively_reload_all_submodules(module, loaded=None):
    for name in dir(module):
        member = getattr(module, name)
        if inspect.ismodule(member) and member not in loaded:
            recursively_reload_all_submodules(member, loaded)
    loaded.add(module)
    reload(module)

import mymodule
recursively_reload_all_submodules(mymodule, set())

Điều này sẽ tải lại toàn bộ cây mô-đun và mô hình con mà bạn cung cấp một cách hiệu quả. Bạn cũng có thể đặt chức năng này trong .ipythonrc (tôi nghĩ) để nó được tải mỗi khi bạn khởi động trình thông dịch.


Điều đó có vẻ tốt, tuy nhiên, có thể là nó không bao gồm các mô-đun hoặc thành viên của các mô-đun được nhập bằng from ... import ...hoặc import ... as. Ít nhất điều đó mang lại cho tôi thường gặp một số rắc rối khi làm việc tương tác trên thiết bị đầu cuối. Tôi đã chuyển sang sử dụng các macro được lưu trữ trong IPython để thực hiện các thao tác nhập và thiết lập cần thiết để bắt đầu hoạt động ở trạng thái được xác định trước.
Bernhard

Nó thực sự bao gồm from ... import ...import ... asmiễn là thứ bạn nhập là một mô-đun. Điều duy nhất mà nó không bao gồm là các mô-đun trong gói không được tải từ __init__.pytệp của nó . Đối với các gói, bạn có thể kiểm tra xem __path__thuộc tính của mô-đun có phải là thư mục không. Nếu có, hãy duyệt qua nó và nhập đệ quy tất cả các mô-đun bạn có thể tìm thấy. Tôi đã không viết phần này vì tác giả đã không yêu cầu một giải pháp cho các gói.
YH Wong

Quả thực điều này có vẻ tốt. Tôi đã nghĩ về khả năng này, đồng thời tôi sẽ mong đợi rằng sẽ có một số chức năng được xây dựng, tức là dựa trên điều này . Tuy nhiên, nó không rõ ràng với tôi làm thế nào để sử dụng này. Sau một số hoạt động đào đáng lẽ phải xảy ra trước khi tôi đăng câu hỏi ban đầu, tôi đã tìm thấy phần mở rộng này .
Alain

Ngoài ra, bạn có thể sử dụng pkgutilđể có được tất cả các mô hình con trong một gói, ngay cả khi gói đó không nhập các mô hình con vào mô đun trên cùng. stackoverflow.com/a/1707786/1243926
osa

bạn cũng phải làm: cho mô-đun trongsys.modules:
aoeu256

2

Một lựa chọn khác:

$ cat << EOF > ~/.ipython/profile_default/startup/50-autoreload.ipy
%load_ext autoreload
%autoreload 2
EOF

Đã xác minh trên ipython và ipython3 v5.1.0 trên Ubuntu 14.04.


1

Thực hành tiêu chuẩn của tôi để tải lại là kết hợp cả hai phương pháp sau lần mở đầu tiên của IPython:

from IPython.lib.deepreload import reload
%load_ext autoreload
%autoreload 2

Tải các mô-đun trước khi làm điều này sẽ khiến chúng không được tải lại, ngay cả với một hướng dẫn reload(module_name). Tôi vẫn, rất hiếm khi gặp các vấn đề không thể giải thích được với các phương thức lớp không tải lại mà tôi chưa xem xét.


1

Lưu ý rằng các đề cập ở trên autoreloadchỉ hoạt động trong IntelliJ nếu bạn lưu tệp thay đổi theo cách thủ công (ví dụ: sử dụng ctrl + s hoặc cmd + s). Nó dường như không hoạt động với tiết kiệm tự động.


Tôi xác nhận đây là trường hợp của PyCharm.
tsando

0

Trên Notebook Jupyter trên Anaconda, thực hiện việc này:

%load_ext autoreload
%autoreload 2

tạo ra thông điệp:

Phần mở rộng tự động tải đã được tải. Để tải lại, sử dụng: %reload_ext autoreload

Có vẻ như nó thích hợp hơn để làm:

%reload_ext autoreload
%autoreload 2

Thông tin phiên bản:

Phiên bản của máy chủ máy tính xách tay là 5.0.0 và đang chạy trên: Python 3.6.2 | Anaconda, Inc. | (mặc định, ngày 20 tháng 9 năm 2017, 13:35:58) [MSC v.1900 32 bit (Intel)]


0

Bất kỳ tiểu dự án nào sẽ không được tải lại bởi điều này, tôi tin rằng bạn phải sử dụng tải lại sâu của IPython cho điều đó.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.