2010-06-10 37 views
27

Tôi đang làm việc trên pypreprocessor là một bộ tiền xử lý có chỉ thị kiểu c và tôi có thể làm cho nó hoạt động giống như một bộ tiền xử lý truyền thống (nó tự tiêu tốn và thực thi mã được xử lý trực tiếp) ngoại trừ nó ngắt thư viện nhập khẩu.Làm cách nào để ghi đè nhập bằng Python?

Vấn đề là: Bộ tiền xử lý chạy qua tệp, xử lý nó, xuất ra tệp tạm thời và exec() tệp tạm thời. Thư viện được nhập khẩu cần phải được xử lý một chút khác nhau, bởi vì chúng không được thực hiện, mà là chúng được nạp và có thể truy cập được vào mô-đun người gọi.

Điều tôi cần làm là: Ngắt nhập (do bộ xử lý trước đang được chạy ở giữa quá trình nhập), tải mã đã xử lý dưới dạng tempModule và thay thế nhập ban đầu bằng tempModule để lừa kịch bản lệnh gọi với việc nhập khẩu tin rằng tempModule là mô-đun ban đầu.

Tôi đã tìm kiếm ở khắp mọi nơi và cho đến nay và không có giải pháp.

này Stack Overflow câu hỏi là gần nhất tôi đã nhìn thấy cho đến nay để cung cấp một câu trả lời: Override namespace in Python

Đây là những gì tôi có.

# Remove the bytecode file created by the first import 
os.remove(moduleName + '.pyc') 

# Remove the first import 
del sys.modules[moduleName] 

# Import the postprocessed module 
tmpModule = __import__(tmpModuleName) 

# Set first module's reference to point to the preprocessed module 
sys.modules[moduleName] = tmpModule 

moduleName là tên của mô-đun gốc và tmpModuleName là tên của tệp mã hậu xử lý.

Phần lạ là giải pháp này vẫn chạy hoàn toàn bình thường như thể mô-đun đầu tiên hoàn thành được tải bình thường; trừ khi bạn loại bỏ dòng cuối cùng, sau đó bạn nhận được một lỗi không tìm thấy mô-đun.

Hy vọng rằng ai đó trên Stack   Luồng tràn biết nhiều hơn về nhập khẩu hơn tôi, bởi vì điều này khiến tôi bối rối.

Lưu ý: Tôi sẽ chỉ trao giải pháp, hoặc, nếu điều này không thể thực hiện được bằng Python; giải thích tốt nhất, chi tiết nhất về lý do tại sao điều này không phải là không thể.

Cập nhật: Đối với bất kỳ ai quan tâm, đây là mã làm việc.

if imp.lock_held() is True: 
    del sys.modules[moduleName] 
    sys.modules[tmpModuleName] = __import__(tmpModuleName) 
    sys.modules[moduleName] = __import__(tmpModuleName) 

phần 'imp.lock_held' phát hiện xem mô-đun có đang được tải dưới dạng thư viện hay không. Các dòng sau làm phần còn lại.

+0

Bạn đang viết một bộ xử lý trước, bạn nên phân tích cú pháp các tệp trước khi biên dịch chúng. I E. bạn sẽ có thể thay đổi 'import module' thành' import post_processed_module' trước khi thời gian python tải tệp của bạn, bằng cách phân tích cú pháp nguồn, sửa đổi nó và đặt nó vào một tệp. Sau khi bạn đã xử lý xong tất cả cây nguồn _then_, bạn có thể thực thi() tệp gốc đã xử lý sau. – Iacopo

+0

@lacopo Thật không may, bộ tiền xử lý cần được nhập vào tệp mà nó đang xử lý trước. Đó là một loại, nhập khẩu các tiền xử lý và tiền xử lý chỉ thị sẽ làm việc trong tập tin này. I E. nó tự tiêu tốn. –

Trả lời

28

Điều này có trả lời câu hỏi của bạn không? Việc nhập khẩu thứ hai hiện các trick.

Mod_1.py

def test_function(): 
    print "Test Function -- Mod 1" 

Mod_2.py

def test_function(): 
    print "Test Function -- Mod 2" 

thử nghiệm.py

#!/usr/bin/python 

import sys 

import Mod_1 

Mod_1.test_function() 

del sys.modules['Mod_1'] 

sys.modules['Mod_1'] = __import__('Mod_2') 

import Mod_1 

Mod_1.test_function() 
+1

Cảm ơn bạn rất nhiều, điều này gần giống với việc triển khai của tôi nhưng nó đã giúp tôi làm đúng với một ví dụ làm việc hữu ích thực tế. Lưu ý: 'Import Mod_1' thứ hai là thừa vì dòng trước khi nó đã xử lý điều đó. –

+1

@EvanPlaice điều quan trọng là bạn CÓ THỂ làm thứ hai 'nhập Mod_1'. Làm nó không tải lại hoặc làm mới mô-đun thực - nó đã bị thay thế vĩnh viễn bởi 'Mod_2'. – jwg

+0

@Ron, tôi cho rằng điều này chỉ áp dụng cho phiên bản Python 2.x. – Abhijeet

-3

Cách tiếp cận rất lạ - để mô phỏng ngôn ngữ cấp thấp với ngôn ngữ cấp cao. Nếu cách đơn giản đầu tiên không hiệu quả, có thể đó là một mục tiêu sai?

BTW, bộ tiền xử lý C chỉ hoạt động với các tệp văn bản và một tập hợp các biến tiền xử lý, không phải là các mô-đun nạp/dỡ ở mức cao.

+2

Ummm. Bộ tiền xử lý không phải là ngôn ngữ cấp cao hoặc thấp. Không có gì ngoài một bước bổ sung trong giai đoạn lexer-parser. Tôi đã chọn c là định dạng để mô phỏng vì hầu hết mọi người đã quen thuộc với nó. Và sự khác biệt duy nhất của bộ tiền xử lý của tôi so với bộ tiền xử lý c là, c thực hiện nó trong thời gian biên dịch; Python phức tạp vì nó biên dịch nhanh chóng. Nếu nó không thể được thực hiện tôi muốn lý do cụ thể tại sao, hoặc ít nhất, một nỗ lực trung thực. –

8

Để xác định hành vi nhập khác hoặc hoàn toàn phá vỡ quy trình nhập, bạn sẽ cần viết móc nhập. Xem PEP 302.

Ví dụ,

import sys 

class MyImporter(object): 

    def find_module(self, module_name, package_path): 
     # Return a loader 
     return self 

    def load_module(self, module_name): 
     # Return a module 
     return self 

sys.meta_path.append(MyImporter()) 

import now_you_can_import_any_name 
print now_you_can_import_any_name 

Nó ra:

<__main__.MyImporter object at 0x009F85F0> 

Vì vậy, về cơ bản nó sẽ trả về một module mới (có thể là bất kỳ đối tượng), trong trường hợp này chính nó. Bạn có thể sử dụng nó để thay đổi hành vi nhập bằng cách trả lại processe_xxx khi nhập xxx.

IMO: Python không cần bộ tiền xử lý. Dù bạn đang thực hiện có thể được thực hiện bằng Python tự do nó tự nhiên rất năng động, ví dụ, lấy trường hợp của ví dụ gỡ lỗi, những gì là sai với việc phải ở phía trên của tập tin

debug = 1 

và sau

if debug: 
    print "wow" 

?

+0

@Anurag gần như ... bắt chước chức năng __import__ mặc định hiện tại. Những gì tôi cần, là thứ có thể loại bỏ việc nhập khẩu cũ và tải một cái mới dưới cái tên cũ. –

+1

@Anurag Để trả lời "tại sao python cần một bộ tiền xử lý?". Cho phép nói rằng bạn có python 2 và python 3 mã trong cùng một tập tin. Vì vậy, bạn rắc 'nếu py2x' báo cáo trên tất cả các mã.Sau đó python 4 đi ra và bạn quyết định thả hỗ trợ cho 2, bây giờ bạn phải tìm tất cả các câu lệnh if cho py2x trong mã. Trong trình tiền xử lý của tôi, nó dễ dàng như yêu cầu xóa tất cả các khối mã trong '#ifdef py2x'. Nó không hướng đến chức năng của nó để bảo trì. Tôi đang cố gắng để tạo ra một lựa chọn tốt hơn để hỗ trợ mã 2x và 3x để cung cấp cho các nhà văn thư viện nhiều động lực hơn để hỗ trợ 3x. –

+0

@Evan Plaice, nhưng tại sao không thể nhập móc được sử dụng để thay đổi tải mô đun cũ và thay vào đó bạn tải mô-đun mới? –

0

Trong Python 2 có mô-đun imputil có vẻ như cung cấp chức năng bạn đang tìm kiếm, nhưng đã bị loại bỏ trong python 3. Nó không được tài liệu lắm nhưng có phần ví dụ cho thấy cách bạn có thể thay thế nhập chuẩn chức năng.

Đối với Python 3 có mô-đun importlib (được giới thiệu trong Python 3.1) có chứa các hàm và lớp để sửa đổi chức năng nhập bằng tất cả các cách. Nó sẽ phù hợp để móc tiền xử lý của bạn vào hệ thống nhập khẩu.

+0

Tôi đã đi xuống con đường đó rồi. importlib được giới thiệu trong 3.1 nhưng anh chàng đã tạo ra nó cũng có một dự án trên PYPI để đưa nó trở lại Python 2.3. Xem http://pypi.python.org/pypi/importlib/1.0.2. –

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