python - Setup.py और पैकेज के साथ पैकेज संस्करण साझा करने का सही तरीका क्या है?




setuptools distutils (5)

setuptools , setuptools , आदि के साथ setup.py में एक पैकेज संस्करण निर्दिष्ट है:

# file: setup.py
...
setup(
name='foobar',
version='1.0.0',
# other attributes
)

मैं पैकेज के भीतर से उसी संस्करण संख्या तक पहुंचने में सक्षम होना चाहता हूं:

>>> import foobar
>>> foobar.__version__
'1.0.0'

मैं अपने पैकेज के __init__.py में __version__ = '1.0.0' जोड़ सकता हूं, लेकिन पैकेज में सरलीकृत इंटरफेस बनाने के लिए मैं अपने पैकेज में अतिरिक्त आयात भी शामिल करना चाहता हूं:

# file: __init__.py

from foobar import foo
from foobar.bar import Bar

__version__ = '1.0.0'

तथा

# file: setup.py

from foobar import __version__
...
setup(
name='foobar',
version=__version__,
# other attributes
)

हालांकि, इन अतिरिक्त आयातों से foobar की स्थापना विफल हो सकती है अगर वे अन्य संकुल आयात करते हैं जो अभी तक स्थापित नहीं हैं। Setup.py और पैकेज के साथ पैकेज संस्करण साझा करने का सही तरीका क्या है?


केवल setup.py में संस्करण सेट करें, और pkg_resources साथ अपना स्वयं का संस्करण पढ़ें, प्रभावी ढंग से setuptools मेटाडेटा से पूछताछ करें:

फ़ाइल: setup.py

setup(
    name='foobar',
    version='1.0.0',
    # other attributes
)

फ़ाइल: __init__.py

from pkg_resources import get_distribution

__version__ = get_distribution('foobar').version

इस काम को सभी मामलों में करने के लिए, जहां आप इसे इंस्टॉल किए बिना इसे चला सकते हैं, DistributionNotFound और वितरण स्थान के लिए परीक्षण करें:

from pkg_resources import get_distribution, DistributionNotFound
import os.path

try:
    _dist = get_distribution('foobar')
    # Normalize case for Windows systems
    dist_loc = os.path.normcase(_dist.location)
    here = os.path.normcase(__file__)
    if not here.startswith(os.path.join(dist_loc, 'foobar')):
        # not installed, but there is another version that *is*
        raise DistributionNotFound
except DistributionNotFound:
    __version__ = 'Please install this project with setup.py'
else:
    __version__ = _dist.version

मुझे विश्वास नहीं है कि इसका एक कैननिक जवाब है, लेकिन मेरी विधि (या तो मैंने जो कुछ अन्य स्थानों में देखा है उससे सीधे कॉपी या थोड़ा tweaked) निम्नानुसार है:

फ़ोल्डर विरासत (केवल प्रासंगिक फाइलें):

package_root/
 |- main_package/
 |   |- __init__.py
 |   `- _version.py
 `- setup.py

main_package/_version.py :

"""Version information."""

# The following line *must* be the last in the module, exactly as formatted:
__version__ = "1.0.0"

main_package/__init__.py :

"""Something nice and descriptive."""

from main_package.some_module import some_function_or_class
# ... etc.
from main_package._version import __version__

__all__ = (
    some_function_or_class,
    # ... etc.
)

setup.py :

from setuptools import setup

setup(
    version=open("main_package/_version.py").readlines()[-1].split()[-1].strip("\"'"),
    # ... etc.
)

... जो पाप के रूप में बदसूरत है ... लेकिन यह काम करता है, और मैंने इसे देखा है या ऐसे लोगों द्वारा वितरित पैकेजों में ऐसा कुछ है जो मुझे एक बेहतर तरीका जानने की उम्मीद करेंगे यदि कोई था।


स्वीकृत उत्तर की आवश्यकता है कि पैकेज स्थापित किया गया है। मेरे मामले में, मुझे स्रोत setup.py से __version__ ( __version__ सहित) निकालने की आवश्यकता थी। Setuptools पैकेज के परीक्षणों को देखते हुए मुझे प्रत्यक्ष और सरल समाधान मिला। _setup_stop_after विशेषता पर अधिक जानकारी के लिए _setup_stop_after मुझे पुरानी मेलिंग सूची पोस्ट में ले जाता है जिसमें _setup_stop_after उल्लेख किया गया है, जो मुझे आवश्यक वास्तविक दस्तावेज़ों में ले जाता है । उसके बाद, यहां सरल समाधान है:

फ़ाइल setup.py :

from setuptools import setup

setup(name='funniest',
      version='0.1',
      description='The funniest joke in the world',
      url='http://github.com/storborg/funniest',
      author='Flying Circus',
      author_email='[email protected]',
      license='MIT',
      packages=['funniest'],
      zip_safe=False)

फ़ाइल extract.py :

from distutils.core import run_setup
dist = run_setup('./setup.py', stop_after='init')
dist.get_version()


स्वीकार्य उत्तर और टिप्पणियों के आधार पर, मैं यही कर रहा हूं:

फ़ाइल: setup.py

setup(
    name='foobar',
    version='1.0.0',
    # other attributes
)

फ़ाइल: __init__.py

from pkg_resources import get_distribution, DistributionNotFound

__project__ = 'foobar'
__version__ = None  # required for initial installation

try:
    __version__ = get_distribution(__project__).version
except DistributionNotFound:
    VERSION = __project__ + '-' + '(local)'
else:
    VERSION = __project__ + '-' + __version__
    from foobar import foo
    from foobar.bar import Bar

स्पष्टीकरण:

  • __project__ स्थापित करने के लिए प्रोजेक्ट का नाम है जो पैकेज के नाम से अलग हो सकता है

  • VERSION है जो मैं अपने कमांड लाइन इंटरफेस में प्रदर्शित करता हूं जब - --version से अनुरोध किया जाता है

  • अतिरिक्त आयात (सरलीकृत पैकेज इंटरफ़ेस के लिए) केवल तब होता है जब प्रोजेक्ट वास्तव में स्थापित किया गया हो







distutils