2017-03-08 22 views
5

Tôi đang cố gắng sử dụng các móc nhập khẩu dựa trên PEP302 để nắm bắt việc nhập mô-đun để tôi có thể có một số tệp .py được mã hóa sẽ được tải vào thời gian chạy. Tôi đang theo mẫu trên python obfuscation tại https://github.com/citrusbyte/python-obfuscation.Chi tiết triển khai PEP302 cần

Ý tưởng cơ bản rất đơn giản: chặn lệnh nhập bằng cách sử dụng hàm Finder() được chèn vào sys.meta_path để bắt chỉ thị nhập. Trình kiểm tra sẽ kiểm tra xem mô-đun có phải là một trong chúng ta muốn xử lý bản thân và nếu có, trả về một đối tượng Trình tải tùy chỉnh. Nếu không, nó bỏ qua việc nhập. Trình tải tùy chỉnh tạo một mục trong sys.modules và đọc trong nguồn mô-đun python và thêm nó vào mô-đun mới được tạo bằng cách sử dụng exec như được định nghĩa trong tài liệu PEP302.

Điều này hoạt động tốt, nhưng tôi có một tình huống cụ thể mà tôi không thể tìm ra. Giả sử 3 tệp, chính, foo và thanh. chính thiết lập móc nhập khẩu sau đó nhập khẩu foo và thanh. foo chính nó nhập khẩu thanh. Vì vậy, tình hình là:

main: 
    set_import_hook 
    import foo 
    import bar 
foo: 
    import bar 
bar: 
    <irrelevant> 

Tôi có các câu lệnh gỡ lỗi trong hàm Finder được đặt làm móc để xem nội dung đang được chuyển.

Khi tôi có mã được mã hóa (ví dụ, mã mà tôi không xử lý và thêm vào sys.modules bản thân mình, các bản in hiển thị các hành vi sau đây:

Finder (foo) 
Finder (bar) called from inside foo when foo itself is loaded 
Finder (bar) called from main after returning from the import foo 

Khi tôi xử lý và tải các tập tin foo và bar bản thân mình, đây là hành vi:.

Finder (foo) 
Finder (foo.bar) tries to load bar in the context of foo 
Finder (bar) called from main after returning from import foo 

Điều này gây ra hai phiên bản của thanh để tồn tại trong sys.modules Nếu bạn nhìn vào sys.modules.keys() trong hai trường hợp, trong trường hợp đầu tiên nó chỉ show foo và bar Trong trường hợp thứ hai nó hiển thị foo, foo.bar và bar.

Tôi không hiểu hành vi này. Quá trình tạo mô-đun được mô tả trong tài liệu PEP 302. Đây là những gì tôi sử dụng:

module = sys.modules.setdefault(name, imp.new_module(name)) 
    module.__file__ = filename 
    module.__path__ = [os.path.dirname(os.path.abspath(file.name))] 
    module.__loader__ = self 
    sys.modules[name] = module 
    exec(src, module.__dict__) 

Cảm ơn.

Trả lời

0

Sau khi xem xét các ví dụ và tài liệu khác nhau, tôi có một câu trả lời một phần.

Trong mã ở trên, tôi nhận thấy rằng tôi không đặt module.__package__. Một nơi nào đó trong quá trình nhập, kết quả là một mục nhập của foo.__package__ = 'foo' được đặt trong định nghĩa mô-đun. Điều này dẫn đến foo được coi là một gói và bất kỳ nhập khẩu nào được coi là nhập khẩu liên quan đến thư mục gói.

Khi chạy chống lại nhập khẩu mà tôi không thiết lập mô-đun, tôi thấy rằng module.__package__ được đặt thành Không theo hệ thống. Nhưng thiết lập module.__package__ = None trong đoạn mã trên không hoạt động. Một cái gì đó thiết lập lại nó để foo.

Giải pháp đã hoạt động là đặt module.__package__ = '' (chuỗi rỗng). Vì vậy, phần hoạt động của mã để thêm mô-đun là:

module = sys.modules.setdefault(name, imp.new_module(name)) 
module.__file__ = filename 
module.__path__ = [os.path.dirname(os.path.abspath(file.name))] 
module.__loader__ = self 
module.__package__ = '' 
sys.modules[name] = module 
exec(src, module.__dict__) 

Điều này hiện đang hoạt động và mô-đun foo và thanh chỉ được nhập một lần. Hành vi của các mô-đun được mã hóa và không được mã hóa trông giống nhau.

Tôi vẫn không hiểu vị trí của module.__package__ được đặt nếu nó không được đặt rõ ràng là ''.

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