سؤال

ما هو __init__.py في بيثون مصدر الدليل ؟

هل كانت مفيدة؟

المحلول

وكان عليه أن يكون جزءا المطلوب من مجموعة ( القديمة، قبل -3.3 "حزمة العادية" ، وليس أحدث 3.3+ "مساحة الاسم حزمة ").

هنا الوثائق.

<اقتباس فقرة>   تعرف

وبيثون نوعين من الحزم، والحزم العادية والحزم مساحة الاسم. حزم العادية هي الحزم التقليدية لأنها كانت موجودة في بيثون 3.2 والإصدارات السابقة. يتم تنفيذ حزمة العادية عادة بمثابة الدليل الذي يحتوي على ملف __init__.py. عند استيراد حزمة العادية، يتم تنفيذ هذا الملف __init__.py ضمنا، وملزمة الكائنات أنها تحدد أسماء في مساحة الاسم الحزمة. يمكن أن يحتوي ملف __init__.py نفس رمز بيثون التي يمكن أن تحتوي على أي وحدة أخرى، وسوف بيثون إضافة بعض سمات إضافية إلى وحدة عندما يتم استيراده.

ولكن فقط انقر على الرابط، فإنه يحتوي على سبيل المثال، مزيد من المعلومات، وشرح حزم مساحة الاسم، وهذا النوع من الحزم دون __init__.py.

نصائح أخرى

تستخدم

والملفات اسمه __init__.py بمناسبة الدلائل على القرص كما بيثون حزمة الدلائل. إذا كان لديك ملفات

mydir/spam/__init__.py
mydir/spam/module.py

ووmydir على المسار الخاص بك، يمكنك استيراد التعليمات البرمجية في module.py ك

import spam.module

أو

from spam import module

إذا قمت بإزالة الملف __init__.py، سوف بيثون لم تعد تبحث عن الوحدات الفرعية داخل هذا الدليل، لذلك سوف تفشل محاولات لاستيراد حدة.

وملف __init__.py عادة ما يكون فارغا، ولكن يمكن استخدامها لتصدير أجزاء مختارة من مجموعة تحت اسم أكثر ملاءمة، وعقد وظائف الراحة، الخ ونظرا لالمثال أعلاه، ومحتويات وحدة الحرف الأول يمكن الوصول إليها ك

import spam

هذا

بالإضافة إلى العلامات دليل باعتبارها حزمة بايثون و تحديد __all__, __init__.py يسمح لك لتحديد أي متغير في حزمة المستوى. القيام بذلك غالبا ما تكون مريحة إذا كان حزمة يعرف شيء سيتم استيراد كثير من الأحيان, في API-مثل الأزياء.هذا النمط يعزز الالتزام Pythonic "شقة أفضل من المتداخلة" الفلسفة.

مثال

هنا هو مثال على واحدة من بلدي المشاريع في كثير من الأحيان استيراد sessionmaker دعا Session التفاعل مع قاعدة البيانات الخاصة بي.كتبت "قاعدة بيانات" حزمة مع عدد قليل من وحدات:

database/
    __init__.py
    schema.py
    insertions.py
    queries.py

بلدي __init__.py يحتوي على التعليمات البرمجية التالية:

import os

from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine

engine = create_engine(os.environ['DATABASE_URL'])
Session = sessionmaker(bind=engine)

منذ ان تحدد Session هنا أنا يمكن أن تبدأ دورة جديدة باستخدام بناء الجملة أدناه.هذا الرمز سيكون نفس تنفيذها من داخل أو خارج "قاعدة بيانات" حزمة الدليل.

from database import Session
session = Session()

بالطبع, هذا هو الراحة الصغيرة-بديل تحديد Session في ملف جديد مثل "create_session.py" في قاعدة بيانات الحزمة ، وبدء جلسات جديدة باستخدام:

from database.create_session import Session
session = Session()

مزيد من القراءة

هناك مثيرة للاهتمام جدا رديت في موضوع تغطية الاستخدامات المناسبة __init__.py هنا:

http://www.reddit.com/r/Python/comments/1bbbwk/whats_your_opinion_on_what_to_include_in_init_py/

رأي الأغلبية يبدو أن __init__.py الملفات يجب أن تكون رقيقة جدا لتجنب مخالفة "صريحة أفضل من ضمني" الفلسفة.

هناك 2 من أهم أسباب __init__.py

  1. للراحة:المستخدمين الآخرين لن تحتاج إلى معرفة وظائف' المكان المحدد في الحزمة الخاصة بك الهرمي.

    your_package/
      __init__.py
      file1.py
      file2.py
        ...
      fileN.py
    
    # in __init__.py
    from file1 import *
    from file2 import *
    ...
    from fileN import *
    
    # in file1.py
    def add():
        pass
    

    ثم الآخرين يمكن أن نطلق إضافة() من قبل

    from your_package import add
    

    دون معرفة file1, مثل

    from your_package.file1 import add
    
  2. إذا كنت تريد شيئا أن تكون تهيئة;على سبيل المثال, تسجيل الدخول (التي ينبغي أن تكون وضعت في المستوى الأعلى):

    import logging.config
    logging.config.dictConfig(Your_logging_config)
    

وملف __init__.py يجعل بيثون الدلائل علاج تحتوي على أنها وحدات.

وعلاوة على ذلك، وهذا هو الملف الأول ليتم تحميلها في وحدة نمطية، لذلك يمكنك استخدامه لتنفيذ التعليمات البرمجية التي تريد تشغيله في كل مرة يتم تحميل وحدة نمطية، أو تحديد الوحدات الفرعية للتصدير.

منذ الثعبان 3.3, __init__.py لم تعد هناك حاجة إلى تحديد الدلائل كما ارداتها الثعبان حزم.

تحقق بيب 420:ضمني مساحة حزم:

الوطنية لدعم حزمة الدلائل التي لا تتطلب __init__.py علامة الملفات تلقائيا تمتد عدة شرائح المسار (مستوحاة من مختلف طرف ثالث نهج مساحة حزم ، كما هو موضح في بيب 420)

هذا الاختبار:

$ mkdir -p /tmp/test_init
$ touch /tmp/test_init/module.py /tmp/test_init/__init__.py
$ tree -at /tmp/test_init
/tmp/test_init
├── module.py
└── __init__.py
$ python3

>>> import sys
>>> sys.path.insert(0, '/tmp')
>>> from test_init import module
>>> import test_init.module

$ rm -f /tmp/test_init/__init__.py
$ tree -at /tmp/test_init
/tmp/test_init
└── module.py
$ python3

>>> import sys
>>> sys.path.insert(0, '/tmp')
>>> from test_init import module
>>> import test_init.module

المراجع:
https://docs.python.org/3/whatsnew/3.3.html#pep-420-implicit-namespace-packages
https://www.python.org/dev/peps/pep-0420/
هو __init__.py ليس المطلوب حزم في بيثون 3?

في بيثون تعريف الحزمة هو بسيط جدا. مثل جافا الهيكل الهرمي وبنية الدليل هي نفسها. ولكن أن يكون لديك __init__.py في مجموعة واحدة. سأشرح الملف __init__.py مع المثال التالي:

package_x/
|--  __init__.py
|--    subPackage_a/
|------  __init__.py
|------  module_m1.py
|--    subPackage_b/
|------  __init__.py
|------  module_n1.py
|------  module_n2.py
|------  module_n3.py

و__init__.py يمكن أن يكون فارغا، طالما كان موجودا. فإنه يشير إلى أن الدليل ينبغي اعتبار مجموعة. بطبيعة الحال، يمكن __init__.py أيضا تعيين المحتوى المناسب.

إذا أضفنا وظيفة في module_n1:

def function_X():
    print "function_X in module_n1"
    return

وبعد تشغيل:

>>>from package_x.subPackage_b.module_n1 import function_X
>>>function_X()

function_X in module_n1 

وثم تابعنا حزمة التسلسل الهرمي، ودعا module_n1 وظيفة. يمكننا استخدام __init__.py في subPackage_b مثل هذا:

__all__ = ['module_n2', 'module_n3']

وبعد تشغيل:

>>>from package_x.subPackage_b import * 
>>>module_n1.function_X()

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named module_n1

وبالتالي تستخدم * المستوردة، حزمة وحدة يخضع ل__init__.py المحتوى.

على الرغم من أن الثعبان يعمل بدون __init__.py الملف لا يزال يجب أن تشمل واحدة.

وتحدد هذه الحزمة يجب أن تعامل على أنها وحدة, ولذلك يشمل ذلك (حتى إذا كان فارغا).

هناك حالة حيث يمكنك فعلا استخدام __init__.py ملف:

تخيل كان لديك الملف التالي هيكل:

main_methods 
    |- methods.py

و methods.py ورد هذا:

def foo():
    return 'foo'

استخدام foo() وسوف تحتاج واحد مما يلي:

from main_methods.methods import foo # Call with foo()
from main_methods import methods # Call with methods.foo()
import main_methods.methods # Call with main_methods.methods.foo()

ربما هناك تحتاج (أو تريد) للحفاظ على methods.py داخل main_methods (أوقات التشغيل/تبعيات على سبيل المثال) ولكن كنت ترغب في استيراد main_methods.


إذا قمت بتغيير اسم methods.py إلى __init__.py ثم يمكنك استخدام foo() فقط استيراد main_methods:

import main_methods
print(main_methods.foo()) # Prints 'foo'

يعمل هذا لأن __init__.py تعامل كجزء من الحزمة.


بعض حزم بيثون فعلا القيام بذلك.مثال على ذلك هو مع سلمان, حيث يعمل import json هو في الواقع المستوردة __init__.py من json حزمة (انظر حزمة بنية الملف هنا):

المصدر مدونة: Lib/json/__init__.py

و__init__.py ستتعامل الدليل هو في وحدة نمطية loadable.

وبالنسبة للأشخاص الذين يفضلون قراءة رمز، أضع اثنين بت الخيميائي تعليق هنا.

$ find /tmp/mydir/
/tmp/mydir/
/tmp/mydir//spam
/tmp/mydir//spam/__init__.py
/tmp/mydir//spam/module.py
$ cd ~
$ python
>>> import sys
>>> sys.path.insert(0, '/tmp/mydir')
>>> from spam import module
>>> module.myfun(3)
9
>>> exit()
$ 
$ rm /tmp/mydir/spam/__init__.py*
$ 
$ python
>>> import sys
>>> sys.path.insert(0, '/tmp/mydir')
>>> from spam import module
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named spam
>>> 

ويسهل استيراد الملفات الثعبان أخرى. عند وضع هذا الملف في دليل (ويقول الاشياء) التي تحتوي على ملفات الحمر أخرى، ثم يمكنك أن تفعل شيئا من هذا القبيل stuff.other الاستيراد.

root\
    stuff\
         other.py

    morestuff\
         another.py

وبدون هذا __init__.py داخل الاشياء الدليل، هل يمكن أن يتم استيراد other.py، لأن بيثون لا أعرف من أين شفرة المصدر لالاشياء وغير قادر على الاعتراف بها كحزمة واحدة.

وملف __init__.py يجعل الواردات سهلا. عندما موجود ضمن حزمة من __init__.py، يمكن استيرادها وظيفة a() من b.py ملف مثل ذلك:

from b import a

وبدون ذلك، ومع ذلك، لا يمكنك الاستيراد مباشرة. لديك لتعديل مسار النظام:

import sys
sys.path.insert(0, 'path/to/b.py')

from b import a
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top