2017-03-08 23 views
5

मैं मॉड्यूल के आयात को पकड़ने के लिए पीईपी 302 आधारित आयात हुक का उपयोग करने का प्रयास कर रहा हूं, इसलिए मुझे कुछ एन्क्रिप्टेड .py फाइलें मिल सकती हैं जो रन टाइम पर लोड हो जाएंगी। मैं https://github.com/citrusbyte/python-obfuscation पर पाइथन obfuscation पर टेम्पलेट का पालन कर रहा हूँ।पीईपी 302 कार्यान्वयन विवरण की आवश्यकता

मूल विचार सरल है: एक आयात निर्देश प्राप्त करने वाले sys.meta_path में डाले गए एक खोजक() फ़ंक्शन का उपयोग करके आयात कमांड को रोकें। खोजक जांचता है कि मॉड्यूल एक है जिसे हम खुद को संभालना चाहते हैं और यदि ऐसा है, तो एक कस्टम लोडर ऑब्जेक्ट देता है। अन्यथा यह आयात को अनदेखा करता है। कस्टम लोडर sys.modules में एक प्रविष्टि बनाता है और पायथन मॉड्यूल स्रोत में पढ़ता है और पीईपी 302 दस्तावेज में परिभाषित निष्पादन का उपयोग करके इसे नए बनाए गए मॉड्यूल में जोड़ता है।

यह अधिकतर ठीक काम करता है, लेकिन मेरे पास एक विशिष्ट स्थिति है जिसे मैं समझ नहीं सकता। 3 फाइलें, मुख्य, foo, और बार मानें। आयात हुक को मुख्य सेट करता है फिर फू आयात करता है, और बार। foo खुद आयात बार। तो स्थिति यह है:

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

मैं खोजक समारोह को देखने के लिए यह क्या भेजी जा रही है हुक के रूप में सेट में डिबग बयान है।

जब मैं एन्क्रिप्ट नहीं किए गए कोड है (यानी, कोड है कि मैं पर कार्रवाई नहीं करते हैं और अपने आप को sys.modules को जोड़ने के लिए, प्रिंटआउट निम्नलिखित व्यवहार दिखाने:

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

जब मैं संसाधित करने और foo और बार फ़ाइलें लोड अपने आप को, यहाँ व्यवहार है:।

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

यह sys.modules में मौजूद बार के दो संस्करणों का कारण बनता है जब आप पहली बार इस मामले में दो मामलों में sys.modules.keys() को देखें, तो यह केवल शो foo और bar। दूसरे मामले में यह foo, foo.bar, और बार दिखाता है।

मुझे इस व्यवहार को समझ में नहीं आता है। मॉड्यूल बनाने की प्रक्रिया पीईपी 302 दस्तावेज़ में वर्णित है। मैं यही उपयोग करता हूं:

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__) 

धन्यवाद।

उत्तर

0

विभिन्न उदाहरणों और दस्तावेज़ीकरण को देखने के समूह के बाद, मेरे पास आंशिक उत्तर है।

उपरोक्त कोड में मैंने देखा कि मैं module.__package__ सेट नहीं कर रहा था। आयात प्रक्रिया में कहीं, जिसके परिणामस्वरूप मॉड्यूल परिभाषा में foo.__package__ = 'foo' सेट किया गया था। इसके परिणामस्वरूप foo को पैकेज माना जा रहा था और किसी भी आयात को पैकेज निर्देशिका से संबंधित आयात माना जा रहा था।

आयात के खिलाफ चलते समय जहां मैं मॉड्यूल सेटअप नहीं कर रहा था, मैंने देखा कि module.__package__ सिस्टम द्वारा किसी को भी सेट नहीं किया गया था। लेकिन ऊपर दिए गए कोड में module.__package__ = None सेट करना काम नहीं किया। कुछ इसे foo करने के लिए रीसेट करें।

समाधान जो समाधान किया गया था module.__package__ = '' (शून्य स्ट्रिंग) सेट करना था। तो मॉड्यूल जोड़ने के लिए कोड का काम कर रहे टुकड़ा है:

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__) 

यह अब काम कर रहा है, और मॉड्यूल foo और बार केवल एक बार आयातित मिलता है। एन्क्रिप्टेड और nonencrypted मॉड्यूल का व्यवहार समान दिखता है।

मुझे अभी भी समझ में नहीं आता है कि module.__package__ सेट हो जाता है यदि यह स्पष्ट रूप से '' पर सेट नहीं है।

संबंधित मुद्दे