__Future__ इंपोर्ट निरपेक्ष_पोर्ट से वास्तव में क्या होता है?


164

मैंने पायथन में पूर्ण आयात के संबंध में एक सवाल का जवाब दिया है, जो मुझे लगा कि मैं पायथन 2.5 चैंज को पढ़ने और पीईपी के साथ पढ़ने के आधार पर समझ गया हूं । हालांकि, पायथन 2.5 को स्थापित करने और ठीक से उपयोग करने का एक उदाहरण शिल्प करने का प्रयास करने पर from __future__ import absolute_import, मुझे लगता है कि चीजें इतनी स्पष्ट नहीं हैं।

ऊपर दिए गए चैंज से सीधे, इस कथन ने पूर्ण रूप से आयात परिवर्तन की मेरी समझ को संक्षेप में प्रस्तुत किया:

मान लें कि आपके पास इस तरह एक पैकेज निर्देशिका है:

pkg/
pkg/__init__.py
pkg/main.py
pkg/string.py

इस नाम के एक पैकेज को परिभाषित करता है pkgयुक्त pkg.mainऔर pkg.stringsubmodules।

मेनफ्रेम मॉड्यूल में कोड पर विचार करें। यदि यह कथन निष्पादित करता है तो क्या होता है import string? पायथन 2.4 और पहले के संस्करण में, यह पहली बार एक सापेक्ष आयात करने के लिए पैकेज की निर्देशिका में दिखेगा, pkg / string.py पाता है, उस फ़ाइल की सामग्री को pkg.stringमॉड्यूल के रूप में आयात करता है , और वह मॉड्यूल नाम के लिए बाध्य होता है"string"pkg.main मॉड्यूल के नाम स्थान में ।

इसलिए मैंने यह सटीक निर्देशिका संरचना बनाई:

$ ls -R
.:
pkg/

./pkg:
__init__.py  main.py  string.py

__init__.pyऔर string.pyखाली हैं।main.pyनिम्नलिखित कोड शामिल हैं:

import string
print string.ascii_uppercase

जैसा कि अपेक्षित था, पायथन 2.5 के साथ इसे चलाना विफल रहता है AttributeError :

$ python2.5 pkg/main.py
Traceback (most recent call last):
  File "pkg/main.py", line 2, in <module>
    print string.ascii_uppercase
AttributeError: 'module' object has no attribute 'ascii_uppercase'

हालाँकि, 2.5 चैंज में आगे, हम इसे पाते हैं (जोर जोड़ा):

पायथन 2.5 में, आप importएक from __future__ import absolute_importनिर्देश का उपयोग करके पूर्ण व्यवहार पर स्विच कर सकते हैं । यह पूर्ण-आयात व्यवहार भविष्य के संस्करण (शायद पायथन 2.7) में डिफ़ॉल्ट हो जाएगा। एक बार पूर्ण आयात डिफ़ॉल्ट होने के बाद, import stringहमेशा मानक लाइब्रेरी का संस्करण मिलेगा।

मैंने इस प्रकार बनाया pkg/main2.py, main.pyलेकिन अतिरिक्त भविष्य के आयात के निर्देश के समान। अब यह इस तरह दिखता है:

from __future__ import absolute_import
import string
print string.ascii_uppercase

पायथन 2.5 के साथ इसे चलाना, हालांकि ... के साथ विफल रहता है AttributeError:

$ python2.5 pkg/main2.py
Traceback (most recent call last):
  File "pkg/main2.py", line 3, in <module>
    print string.ascii_uppercase
AttributeError: 'module' object has no attribute 'ascii_uppercase'

यह सुंदर साफ बयान है कि विपरीत import stringहोगा हमेशा पूर्ण आयात के साथ सक्षम एसटीडी-लिब संस्करण पाते हैं। चेतावनी के बावजूद कि पूर्ण आयात "नया डिफ़ॉल्ट" व्यवहार बनने वाला है, मैंने __future__निर्देश के साथ या उसके बिना पायथन 2.7 दोनों का उपयोग करके इस समस्या को मारा :

$ python2.7 pkg/main.py
Traceback (most recent call last):
  File "pkg/main.py", line 2, in <module>
    print string.ascii_uppercase
AttributeError: 'module' object has no attribute 'ascii_uppercase'

$ python2.7 pkg/main2.py
Traceback (most recent call last):
  File "pkg/main2.py", line 3, in <module>
    print string.ascii_uppercase
AttributeError: 'module' object has no attribute 'ascii_uppercase'

पायथन 3.5 के साथ, इसके साथ या उसके बिना ( printकथन को दोनों फाइलों में बदला गया है):

$ python3.5 pkg/main.py
Traceback (most recent call last):
  File "pkg/main.py", line 2, in <module>
    print(string.ascii_uppercase)
AttributeError: module 'string' has no attribute 'ascii_uppercase'

$ python3.5 pkg/main2.py
Traceback (most recent call last):
  File "pkg/main2.py", line 3, in <module>
    print(string.ascii_uppercase)
AttributeError: module 'string' has no attribute 'ascii_uppercase'

मैंने इसके अन्य रूपों का परीक्षण किया है। इसके बजाय string.py, मैंने एक खाली मॉड्यूल बनाया है - stringकेवल एक खाली नाम वाली एक निर्देशिका __init__.py- और इसके बजाय से आयात जारी करने के बजाय main.py, मेरे पास हैcdpkg REPL से सीधे आयात करने और चलाने के लिए है। न तो इन विविधताओं (और न ही उनमें से एक संयोजन) ने उपरोक्त परिणामों को बदल दिया। मैं इस बारे में जो मैंने पढ़ा है उसके साथ सामंजस्य नहीं बना सकता__future__निर्देश और पूर्ण आयात के ।

ऐसा लगता है कि यह निम्नलिखित द्वारा आसानी से पता लगाया जा सकता है (यह पायथन 2 डॉक्स से है लेकिन यह कथन पायथन 3 के लिए एक ही डॉक्स में अपरिवर्तित है):

sys.path

(...)

जैसा कि प्रोग्राम स्टार्टअप पर शुरू किया गया था, इस सूची का पहला आइटम, path[0]स्क्रिप्ट युक्त निर्देशिका है जिसका उपयोग पायथन इंटरप्रेटर को लागू करने के लिए किया गया था। यदि स्क्रिप्ट निर्देशिका उपलब्ध नहीं है (उदाहरण के लिए यदि इंटरप्रेन्योर को अंतःक्रियात्मक रूप से आमंत्रित किया जाता है या यदि स्क्रिप्ट को मानक इनपुट से पढ़ा जाता है), path[0]तो खाली स्ट्रिंग है, जो पहले पायथन को वर्तमान निर्देशिका में खोज मॉड्यूल को निर्देशित करता है।

तो मुझे क्या याद आ रही है? __future__बयान क्यों प्रतीत होता है कि यह क्या कहता है, और प्रलेखन के इन दो वर्गों के बीच और साथ ही वर्णित और वास्तविक व्यवहार के बीच इस विरोधाभास का क्या संकल्प है?


जवाबों:


104

चैंज स्लॉग शब्द है। from __future__ import absolute_importइस बात की परवाह नहीं करता है कि क्या कुछ मानक पुस्तकालय का हिस्सा है, और import stringहमेशा आपको पूर्ण आयात पर मानक-पुस्तकालय मॉड्यूल नहीं देगा।

from __future__ import absolute_importइसका मतलब है कि यदि आप import string, पायथन हमेशा के stringबजाय एक शीर्ष-स्तरीय मॉड्यूल की तलाश करेंगे current_package.string। हालाँकि, यह तर्क को प्रभावित नहीं करता है कि पायथन का उपयोग यह तय करने के लिए करता है कि फ़ाइल क्या stringमॉड्यूल है। जब तुम करोगे

python pkg/script.py

pkg/script.pyअजगर के लिए एक पैकेज के हिस्से की तरह नहीं दिखता है। सामान्य प्रक्रियाओं के बाद, pkgनिर्देशिका को पथ में जोड़ा जाता है, और निर्देशिका की सभी .pyफाइलें pkgशीर्ष-स्तरीय मॉड्यूल की तरह दिखती हैं। नहीं import stringपाता pkg/string.pyहै क्योंकि यह एक रिश्तेदार आयात कर रहा है, लेकिन क्योंकि pkg/string.pyयह शीर्ष-स्तरीय मॉड्यूल प्रतीत होता है string। तथ्य यह है कि यह मानक-पुस्तकालय stringमॉड्यूल नहीं है।

फ़ाइल को pkgपैकेज के भाग के रूप में चलाने के लिए , आप कर सकते हैं

python -m pkg.script

इस मामले में, pkg निर्देशिका को पथ में नहीं जोड़ा जाएगा। हालांकि, वर्तमान निर्देशिका को पथ में जोड़ा जाएगा।

आप पायलटन को फ़ाइल के रूप में चलाने पर भी पैकेज के pkg/script.pyहिस्से के रूप में व्यवहार करने के लिए कुछ बॉयलरप्लेट जोड़ सकते हैं pkg:

if __name__ == '__main__' and __package__ is None:
    __package__ = 'pkg'

हालांकि, यह प्रभावित नहीं करेगा sys.pathpkgनिर्देशिका को पथ से हटाने के लिए आपको कुछ अतिरिक्त हैंडलिंग की आवश्यकता होगी , और यदि pkgमाता-पिता निर्देशिका पथ पर नहीं है, तो आपको उस पथ पर भी चिपकना होगा।


2
ठीक है, मेरा मतलब है, मुझे वह मिल गया है। ठीक यही व्यवहार मेरे पद का दस्तावेज है। उस के चेहरे में, हालांकि, दो सवाल: (1.) "अगर यह बिल्कुल सच नहीं है", तो डॉक्स स्पष्ट रूप से क्यों कहते हैं? और, (2.) कैसे, तब, क्या import stringआप गलती से इसे छाया करते हैं, कम से कम बिना राइफल के sys.modules। क्या from __future__ import absolute_importइसे रोकने का इरादा नहीं है? यह क्या करता है? (पुनश्च, मैं नीच नहीं हूं।)
दो-बिट अल्केमिस्ट

14
ऐ, वह मैं था ('उपयोगी नहीं' के लिए डाउनवोट, 'गलत' के लिए नहीं था)। यह नीचे के खंड से स्पष्ट है कि ओपी कैसे sys.pathकाम करता है, और वास्तविक प्रश्न को बिल्कुल भी संबोधित नहीं किया गया है। यही है, वास्तव में क्या करता from __future__ import absolute_importहै?
wim

5
@ टू-बिटअल्केमिस्ट: 1) चेंजलॉग शिथिल-शब्द और गैर-आदर्श है। 2) आप इसे छाया देना बंद कर दें। यहां तक ​​कि अगर आप अपने स्वयं के शीर्ष-स्तरीय मॉड्यूल के साथ छाया हुआ है, तो आपको sys.modulesमानक-पुस्तकालय stringमॉड्यूल भी नहीं मिलेगा । from __future__ import absolute_importटॉप-लेवल मॉड्यूल्स को टॉप-लेवल मॉड्यूल्स को शैडो करने से रोकने का मतलब नहीं है; यह पैकेज-आंतरिक मॉड्यूल को शीर्ष-स्तरीय मॉड्यूल को छायांकित करने से रोकने वाला है। यदि आप फ़ाइल को pkgपैकेज के भाग के रूप में चलाते हैं , तो पैकेज की आंतरिक फ़ाइलें शीर्ष-स्तर के रूप में दिखना बंद हो जाती हैं।
user2357112

@ दो-बिटकेमिस्ट: उत्तर संशोधित। क्या यह संस्करण अधिक मददगार है?
user2357112

1
@storen: मान लें pkgकि आयात खोज पथ पर एक पैकेज है, जो होना चाहिए python -m pkg.main-mएक मॉड्यूल नाम की जरूरत है, एक फ़ाइल पथ नहीं।
user2357112 मोनिका को सपोर्ट करता है

44

पूर्ण और सापेक्ष आयातों के बीच का अंतर केवल तभी खेला जाता है जब आप किसी पैकेज से मॉड्यूल आयात करते हैं और वह मॉड्यूल उस पैकेज से अन्य सबमॉड्यूल आयात करता है। फर्क देखें:

$ mkdir pkg
$ touch pkg/__init__.py
$ touch pkg/string.py
$ echo 'import string;print(string.ascii_uppercase)' > pkg/main1.py
$ python2
Python 2.7.9 (default, Dec 13 2014, 18:02:08) [GCC] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import pkg.main1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "pkg/main1.py", line 1, in <module>
    import string;print(string.ascii_uppercase)
AttributeError: 'module' object has no attribute 'ascii_uppercase'
>>> 
$ echo 'from __future__ import absolute_import;import string;print(string.ascii_uppercase)' > pkg/main2.py
$ python2
Python 2.7.9 (default, Dec 13 2014, 18:02:08) [GCC] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import pkg.main2
ABCDEFGHIJKLMNOPQRSTUVWXYZ
>>> 

विशेष रूप से:

$ python2 pkg/main2.py
Traceback (most recent call last):
  File "pkg/main2.py", line 1, in <module>
    from __future__ import absolute_import;import string;print(string.ascii_uppercase)
AttributeError: 'module' object has no attribute 'ascii_uppercase'
$ python2
Python 2.7.9 (default, Dec 13 2014, 18:02:08) [GCC] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import pkg.main2
ABCDEFGHIJKLMNOPQRSTUVWXYZ
>>> 
$ python2 -m pkg.main2
ABCDEFGHIJKLMNOPQRSTUVWXYZ

ध्यान दें कि python2 pkg/main2.pyएक अलग व्यवहार है फिर लॉन्च करना python2और फिर आयात करना pkg.main2(जो -mस्विच का उपयोग करने के बराबर है )।

यदि आप कभी भी एक पैकेज के सबमॉड्यूल को चलाना चाहते हैं तो हमेशा -mस्विच का उपयोग करें जो दुभाषिया को चैन करने से रोकता हैsys.path सूची का और सही तरीके से सबमॉड्यूल के शब्दार्थ को संभालता है।

इसके अलावा, मैं पैकेज सबमॉड्यूल के लिए स्पष्ट सापेक्ष आयात का उपयोग करना पसंद करता हूं क्योंकि वे विफलता के मामले में अधिक शब्दार्थ और बेहतर त्रुटि संदेश प्रदान करते हैं।


तो अनिवार्य रूप से यह केवल एक संकीर्ण मामले के लिए काम करता है जहां आप "वर्तमान निर्देशिका" समस्या से बच गए हैं? यह पीईपी 328 और 2.5 चैंज द्वारा वर्णित की तुलना में बहुत कमजोर कार्यान्वयन प्रतीत होता है। क्या आप मानते हैं कि दस्तावेज गलत है?
दो-बिट अल्केमिस्ट

@ टू-बिटअल्केमिस्ट वास्तव में आप जो कर रहे हैं वह "संकीर्ण मामला" है। आप निष्पादित करने के लिए केवल एक ही अजगर फ़ाइल लॉन्च करते हैं, लेकिन इससे सैकड़ों आयात हो सकते हैं। एक पैकेज के सबमॉड्यूल्स को बस निष्पादित नहीं किया जाना चाहिए, बस।
बकुरीउ

क्यों python2 pkg/main2.pyएक अलग व्यवहार है तो python2 लॉन्च करना और फिर pkg.main2 आयात करना?
12

1
@storen ऐसा इसलिए है क्योंकि सापेक्ष आयात के साथ व्यवहार बदल जाता है। जब आप pkg/main2.pyअजगर (संस्करण 2) लॉन्च करते हैं तो पैकेज के रूप में नहीं मानते हैं pkg। उपयोग python2 -m pkg.main2या आयात करते समय यह ध्यान में रखें कि pkgएक पैकेज है।
बाकुरिउ
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.