Tải lại tất cả các mô-đun Python

Thư viện này triển khai trình tải lại mô-đun dựa trên phụ thuộc cho Python. Không giống như hàm dựng sẵn, trình tải lại này sẽ tải lại mô-đun được yêu cầu và tất cả các mô-đun khác phụ thuộc vào mô-đun đó

Một cuộc thảo luận chi tiết về việc triển khai trình tải lại có sẵn tại đây

http. //www. không thể xóa nhòa. org/ink/python-reloading/

Cách sử dụng

Trình tải lại hoạt động bằng cách theo dõi các phụ thuộc giữa các mô-đun đã nhập. Trước tiên, nó phải được bật để theo dõi các phụ thuộc đó. Trình tải lại không có thông tin phụ thuộc cho các mô-đun đã được nhập trước khi nó được bật hoặc sau khi nó bị tắt, vì vậy bạn có thể muốn bật trình tải lại sớm trong quá trình khởi động ứng dụng của mình

import reloader
reloader.enable[]

# Import additional modules
import module1
import module2

Để tải lại mô-đun đã nhập theo cách thủ công, hãy chuyển mô-đun đó sang phương thức reload[] của trình tải lại

import example
reloader.reload[example]

Lưu ý rằng bạn phải truyền chính đối tượng mô-đun chứ không phải chuỗi chứa tên mô-đun. Nếu bạn chỉ có tên của mô-đun, bạn có thể tìm nạp đối tượng mô-đun từ hệ thống chung. từ điển mô-đun

reloader.reload[sys.modules['example']]

Bạn cũng có thể truy vấn các phần phụ thuộc của mô-đun cho mục đích cung cấp thông tin hoặc gỡ lỗi

reloader.get_dependencies[example]

Bạn có thể tắt tính năng theo dõi phụ thuộc của trình tải lại bất kỳ lúc nào

reloader.disable[]

Mô-đun danh sách đen

Có thể đôi khi bạn không muốn tải lại một mô-đun và hệ thống phân cấp phụ thuộc của nó. Mô-đun có thể hiếm khi thay đổi và tốn kém khi nhập. Để hỗ trợ những trường hợp này, bạn có thể hiển thị rõ ràng các mô-đun "danh sách đen" từ quá trình tải lại bằng cách sử dụng đối số danh sách đen để bật[]

reloader.enable[blacklist=['os', 'ConfigParser']]

Danh sách đen có thể là bất kỳ danh sách có thể lặp lại nào liệt kê các tên mô-đun đủ điều kiện cần được bỏ qua. Lưu ý rằng các mô-đun được liệt kê trong danh sách đen sẽ vẫn xuất hiện trong biểu đồ phụ thuộc về tính đầy đủ;

Một ví dụ tương tác

Ví dụ này cho thấy trình tải lại có thể được sử dụng dễ dàng như thế nào từ trình thông dịch Python tương tác. Hãy tưởng tượng bạn có ví dụ mô-đun. py mở trong trình soạn thảo văn bản và nó chứa nội dung sau

print "I am example.py"

Phiên tương tác của chúng tôi bắt đầu như thế này

>>> import reloader
>>> reloader.enable[]
>>> import example
I am example.py

Bây giờ sửa đổi ví dụ. py trong trình soạn thảo văn bản của bạn. Sau đó, bạn có thể tải lại ví dụ trong phiên tương tác của mình

________số 8

Đây là một ví dụ đơn giản không thể hiện đầy đủ sức mạnh của tính năng theo dõi mô-đun dựa trên sự phụ thuộc của trình tải lại, nhưng hy vọng nó sẽ minh họa cách sử dụng và tiện ích cơ bản của hệ thống

Gọi lại __reload__[]

Nếu một mô-đun có chức năng __reload__[], thì nó sẽ được gọi với một bản sao từ điển của mô-đun ban đầu sau khi được tải lại. Điều này cung cấp một cơ chế thuận tiện để duy trì trạng thái giữa các lần tải lại

Hãy xem xét một mô-đun có tên là đếm có chứa đoạn mã sau

COUNTER = 0

Biến COUNTER của mô-đun sẽ được đặt lại về 0 khi mô-đun được tải lại

import example
reloader.reload[example]
0

Chúng ta có thể duy trì giá trị của COUNTER qua các lần tải lại bằng cách thêm hàm __reload__[] vào mô-đun đếm

Viết mô-đun đầu tiên của tôi bằng Python là một trải nghiệm khó hiểu. Như thường lệ, khi tôi thử nghiệm nó trong Python REPL tương tác, phiên bản đầu tiên hóa ra có một số lỗi [phiên bản thứ hai và thứ ba cũng vậy 😉]

Tốt thôi - tôi nghĩ - Tôi sẽ chỉ sửa mô-đun và nhập lại nó

Nhưng, thật ngạc nhiên, gọi điện cho

reloader.reload[sys.modules['example']]
9 không cập nhật mã.
reloader.get_dependencies[example]
0 vẫn còn lỗi mà tôi vừa sửa. Em kiểm tra lại xem có sửa đúng file không, nhập lại mà vẫn không được. Hóa ra, như StackOverflow đã giải thích một cách tử tế, rằng bạn không thể nhập lại một mô-đun. Nếu bạn đã nhập một mô-đun [
reloader.get_dependencies[example]
1] hoặc một hàm [
reloader.get_dependencies[example]
2] trong phiên Python của mình và bạn cố gắng nhập lại, sẽ không có gì xảy ra. Không thành vấn đề nếu bạn sử dụng tiêu chuẩn Python REPL hoặc IPython

Nhập bằng Python hoạt động như thế nào?

Hóa ra, vì lý do hiệu quả, khi bạn nhập một mô-đun trong phiên Python tương tác, trình thông dịch Python sẽ thực hiện hai bước

  1. Đầu tiên, nó kiểm tra xem mô-đun đã được lưu trong bộ nhớ cache trong từ điển
    reloader.get_dependencies[example]
    3 chưa
  2. Và chỉ khi nó không có ở đó, nó mới thực sự nhập mô-đun

Điều đó có nghĩa là, nếu bạn đã nhập mô-đun [hoặc đã nhập một mô-đun khác tham chiếu đến mô-đun này] và bạn cố gắng nhập lại mô-đun đó, Python sẽ bỏ qua yêu cầu này. Bạn có thể đọc thêm về cách nhập hoạt động trong tài liệu

Vì vậy, nếu tôi không thể nhập lại một mô-đun, điều đó có nghĩa là tôi phải khởi động lại Python mỗi lần?

Làm cách nào để nhập lại một mô-đun?

Cách dễ nhất là thoát phiên tương tác của bạn và bắt đầu lại. Nó hoạt động tốt nếu bạn không quan tâm đến việc bảo toàn dữ liệu mà bạn đã có trong phiên của mình, chẳng hạn như các hàm bạn đã viết và các biến mà bạn đã tính toán. Nhưng thường thì bạn không muốn khởi động lại REPL, vì vậy có nhiều cách tốt hơn

Vì chúng tôi biết rằng trình thông dịch sẽ tìm kiếm mô-đun đầu tiên trong từ điển

import example
reloader.reload[example]
10, chúng tôi chỉ cần xóa mô-đun của mình khỏi từ điển này. Và nó sẽ hoạt động trong hầu hết các trường hợp, nhưng có một số lưu ý. Nếu mô-đun của bạn được tham chiếu từ một mô-đun khác, có khả năng là bạn vẫn không thể nhập lại mô-đun đó. Vì vậy, đừng làm điều này. có một cách tốt hơn

Giải pháp được khuyến nghị là sử dụng hàm

import example
reloader.reload[example]
11. Chức năng này được thiết kế chính xác để nhập lại các mô-đun đã được nhập trước đó. Để tải lại mô-đun của bạn, bạn cần chạy

import example
reloader.reload[example]
3

Vì vậy, đó là cách bạn có thể nhập lại một mô-đun trong Python. Và nếu bạn không sử dụng IPython, đây là lúc các tùy chọn của bạn kết thúc. Nhưng người dùng IPython có một số giải pháp thú vị khác cho vấn đề này

%chạy

Nếu bạn không quan tâm đến việc thực sự "nhập" mô-đun của mình và tất cả những gì bạn cần là chạy một số chức năng được xác định trong một tệp, bạn có thể thực thi tệp đó thay thế. Nó sẽ chạy tất cả các lệnh như thể bạn sao chép và dán chúng vào phiên IPython của mình. Bạn có thể chạy lại một tệp bao nhiêu lần tùy thích và nó sẽ luôn cập nhật tất cả các chức năng. Chạy một tệp trong IPython cực kỳ dễ dàng

import example
reloader.reload[example]
1

Tôi đã gian lận một chút khi nói rằng tùy chọn này không có sẵn trong Python REPL tiêu chuẩn. Đúng vậy, nhưng nó yêu cầu gõ nhiều hơn

import example
reloader.reload[example]
5

Thành thật mà nói, nếu tôi phải gõ tất cả những thứ này, tôi cũng có thể sử dụng

import example
reloader.reload[example]
11 thay thế

Tất cả các tùy chọn đó đều tuyệt vời, nhưng nếu bạn cũng tệ như tôi khi viết mã và bạn mắc nhiều lỗi, thì điều đó có nghĩa là phải tải lại rất nhiều. Và gõ

import example
reloader.reload[example]
11 /
import example
reloader.reload[example]
14 /
import example
reloader.reload[example]
15 này thật khó chịu. Sẽ thật tuyệt nếu có cách tự động tải lại một mô-đun phải không?

%autoreload để giải cứu

Một trong những phương pháp kỳ diệu khác trong IPython có liên quan đến việc tải lại các mô-đun. Nó được gọi là %autoreload. Nó không được bật theo mặc định, vì vậy bạn phải tải nó dưới dạng tiện ích mở rộng

reloader.reload[sys.modules['example']]
0

Bây giờ, bạn có thể bật tự động tải lại

reloader.reload[sys.modules['example']]
1

Và mỗi khi bạn thực thi một số mã, IPython sẽ nhập lại tất cả các mô-đun để đảm bảo rằng bạn đang sử dụng các phiên bản mới nhất có thể

Có 3 tùy chọn cấu hình mà bạn có thể thiết lập

  • import example
    reloader.reload[example]
    16 - vô hiệu hóa tự động tải lại. Đây là thiết lập mặc định
  • import example
    reloader.reload[example]
    17 - nó sẽ chỉ tự động tải lại các mô-đun đã được nhập bằng hàm
    import example
    reloader.reload[example]
    18 [e. g
    import example
    reloader.reload[example]
    19]. Đó là một lựa chọn tốt nếu bạn chỉ muốn tự động tải lại cụ thể một mô-đun đã chọn
  • import example
    reloader.reload[example]
    50 - tự động tải lại tất cả các mô-đun. Cách tuyệt vời để viết và kiểm tra các mô-đun của bạn dễ dàng hơn nhiều

Tuyệt vời, có lưu ý gì không?

  • IPython với %autoreload được kích hoạt sẽ chậm hơn một chút. IPython khá thông minh về những gì cần tải lại. Nó sẽ kiểm tra dấu thời gian sửa đổi của các mô-đun và so sánh chúng với thời điểm chúng được nhập. Nhưng việc kiểm tra này [và cuối cùng là nhập lại các mô-đun đã sửa đổi] sẽ vẫn mất một khoảng thời gian. Nó sẽ không chậm đến mức bạn sẽ cảm thấy nó [trừ khi bạn có các mô-đun mất vài giây để nhập], nhưng rõ ràng là nó sẽ chạy nhanh hơn nếu bạn tắt tính năng tự động tải lại
  • Như đã chỉ ra trong tài liệu, %autoreload không đáng tin cậy 100% và có thể có một số hành vi không mong muốn. Tôi chưa bao giờ nhận thấy bất kỳ vấn đề nào, nhưng một số người dùng reddit đã đề cập rằng nó có thể không hoạt động chính xác đối với các mô-đun nâng cao hơn [với các lớp, v.v. ]
  • Bạn cần đảm bảo rằng bạn không có lỗi cú pháp trong các mô-đun khi chạy các lệnh IPython. Tôi thường bắt đầu viết một số mã trong một tệp và ở giữa lệnh, tôi chuyển sang IPython để nhanh chóng kiểm tra thứ gì đó. Và khi tôi thực thi một số mã trong IPython, nó sẽ cố gắng nhập lại tệp mà tôi vừa sửa đổi [tệp có lệnh viết một nửa] và ném SyntaxError. Điều tốt là - sau khi xảy ra lỗi, bạn vẫn sẽ nhận được đầu ra của lệnh mà bạn đã chạy. Vì vậy, đối với tôi, đó là một phiền toái nhỏ, không phải là một vấn đề thực sự. Bạn có thể dễ dàng giải quyết nó bằng cách chạy hai phiên IPython - một phiên để kiểm tra mô-đun [đã bật% autoreload] và phiên còn lại để chạy một số lệnh ngẫu nhiên và tra cứu mọi thứ trong tài liệu

Đây là cách hoạt động của

import example
reloader.reload[example]
51 trong thực tế [video này được ghi lại bằng asciinema và nếu bạn xem nó trên điện thoại di động, một phần của nhận xét cuối cùng sẽ bị cắt - nó nói. #không có autoreload, chúng ta vẫn thấy "xin chào. "]

Vì vậy, nếu bạn chưa biết về

import example
reloader.reload[example]
51, hãy thử nó vào lần tới khi bạn làm việc với một mô-đun trong Python

Chủ Đề