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.