2015-01-23 33 views
6

Trong Python bạn có thể tải lại một mô-đun như sau ...gói Reloading (và các môđun con của họ) một cách đệ quy bằng Python

import foobar 

import importlib 
importlib.reload(foobar) 

này làm việc cho .py tác phẩm, nhưng đối với Python gói nó sẽ chỉ tải lại gói và không phải bất kỳ mô đun phụ lồng nhau nào.

Với gói:

  • foobar/__init__.py
  • foobar/spam.py
  • foobar/eggs.py

Python Script:

import foobar 

# assume `spam/__init__.py` is importing `.spam` 
# so we dont need an explicit import. 
print(foobar.spam) # ok 

import importlib 
importlib.reload(foobar) 
# foobar.spam WONT be reloaded. 

Không được đề nghị thứ là một lỗi, nhưng có lần hữu ích của nó để tải lại một gói và tất cả các mô-đun con của nó. (Nếu bạn muốn chỉnh sửa mô-đun trong khi tập lệnh chạy ví dụ).

Một số cách tốt để đệ quy tải lại gói bằng Python là gì?

Ghi chú:

  • Đối với mục đích của câu hỏi này giả định Python3.x mới nhất

    (hiện đang sử dụng importlib)

  • phép rằng điều này có requre một số chỉnh sửa để các module mình.
  • Giả sử nhập khẩu ký tự đại diện không được sử dụng (from foobar import *), vì chúng có thể làm phức tạp logic tải lại.
+2

IPython cung cấp module 'IPython.lib.deepreload' cho nạp lại đệ quy. Bạn có thể tìm thấy [mã tại đây] (https://github.com/ipython/ipython/blob/master/IPython/lib/deepreload.py). Thật thú vị, mô-đun là 285 sloc. – jme

+0

Gợi ý tuyệt vời, nhưng thay thế móc nhập khẩu là một loại giải pháp trọng lượng nặng (có ý nghĩa đối với IPython) nhưng không phải một số đoạn tôi muốn trong dự án của tôi chỉ để tải lại làm việc một cách hữu ích hơn một chút. – ideasman42

Trả lời

-1

Một cái gì đó như thế này, có thể?

import importlib 
import types 

def reloadall(module): 
    importlib.reload(module) 
    for child in module: 
     if isinstance(child, types.ModuleType): 
      reloadall(child) 
+0

bạn đã kiểm tra điều này? Tôi nhận được 'TypeError: 'module' đối tượng không thể lặp lại', Ngoài ra điều này sẽ recurse infinately nếu mô-đun tham khảo eachother, và khá chắc chắn cách làm việc của không gian tên - điều này sẽ chỉ cập nhật các mô-đun cục bộ, nhưng không submodule trong gói. – ideasman42

+0

Tôi đã kiểm tra một phần nó. 'Type (module)' là gì khi nó cho bạn biết nó không thể lặp lại được? Chuỗi cuộc gọi đến đó là gì? –

+0

Nó là một '', chỉ cần thêm 'reloadall (types)' ở dưới cùng của ví dụ – ideasman42

3

Có chức năng tải đệ quy một gói đệ quy. Kiểm tra kỹ xem các mô-đun được tải lại có được cập nhật trong các mô-đun mà chúng được sử dụng hay không và các vấn đề với đệ quy vô hạn được kiểm tra.

Một restruction là nó cần phải chạy trên một gói (mà chỉ có ý nghĩa đối với các gói nào)

import os 
import types 
import importlib 


def reload_package(package): 
    assert(hasattr(package, "__package__")) 
    fn = package.__file__ 
    fn_dir = os.path.dirname(fn) + os.sep 
    module_visit = {fn} 
    del fn 

    def reload_recursive_ex(module): 
     importlib.reload(module) 

     for module_child in vars(module).values(): 
      if isinstance(module_child, types.ModuleType): 
       fn_child = getattr(module_child, "__file__", None) 
       if (fn_child is not None) and fn_child.startswith(fn_dir): 
        if fn_child not in module_visit: 
         # print("reloading:", fn_child, "from", module) 
         module_visit.add(fn_child) 
         reload_recursive_ex(module_child) 

    return reload_recursive_ex(package) 

# example use 
import os 
reload_package(os) 
+1

chức năng này không hoàn toàn chính xác, xem xét có hai mô-đun con A và B. các đối tượng trong A phụ thuộc vào B. Giả sử A được nạp lại trước, A sẽ nhập B cũ (vì B chưa nạp lại). Nó kết quả trong một không hoàn toàn cập nhật A. –

+0

Điểm tốt, tôi sẽ xem xét một sửa chữa khi tôi nhận được một thời gian. – ideasman42

Các vấn đề liên quan