मैं अपने पैकेज में setup.py (setuptools) में परिभाषित संस्करण कैसे प्राप्त कर सकता हूं?


153

मैं setup.pyअपने पैकेज ( --version, या अन्य उद्देश्यों) से संस्करण को कैसे परिभाषित कर सकता हूं ?


3
मुझे लगता है कि यह लगभग समान प्रश्न है stackoverflow.com/questions/458550/…
ज़ूको

जवाबों:


246

पहले से इंस्टॉल किए गए वितरण के संस्करण स्ट्रिंग से पूछताछ करें

रनटाइम पर अपने पैकेज के अंदर से संस्करण को पुनः प्राप्त करने के लिए (वास्तव में आपका प्रश्न क्या प्रतीत होता है), आप उपयोग कर सकते हैं:

import pkg_resources  # part of setuptools
version = pkg_resources.require("MyProject")[0].version

इंस्टॉल के दौरान उपयोग के लिए स्टोर संस्करण स्ट्रिंग

यदि आप दूसरे रास्ते पर जाना चाहते हैं (जो प्रतीत होता है कि अन्य उत्तर लेखक यहां दिखाई देते हैं, तो सोचा था कि आप पूछ रहे थे), संस्करण स्ट्रिंग को एक अलग फ़ाइल में रखें और उस फ़ाइल की सामग्री को पढ़ें setup.py

आप अपने पैकेज में एक __version__पंक्ति के साथ एक वर्जनहोम बना सकते हैं , फिर इसे सेटअप-थ्रू उपयोग करके पढ़ सकते हैं execfile('mypackage/version.py'), ताकि यह __version__सेटअप-थ्रीडी नामस्थान में सेट हो जाए ।

यदि आप एक बहुत ही सरल तरीका चाहते हैं जो सभी पायथन संस्करणों और यहां तक ​​कि गैर-पायथन भाषाओं के साथ काम करेगा जिन्हें संस्करण स्ट्रिंग तक पहुंच की आवश्यकता हो सकती है:

संस्करण स्ट्रिंग को एक सादा पाठ फ़ाइल की एकमात्र सामग्री के रूप में संग्रहीत करें, जैसे नाम VERSION, और उस फ़ाइल को पढ़ने के दौरान setup.py

version_file = open(os.path.join(mypackage_root_dir, 'VERSION'))
version = version_file.read().strip()

एक ही VERSIONफ़ाइल तब किसी भी अन्य प्रोग्राम में बिल्कुल गैर-पायथन लोगों के समान काम करेगी, और आपको केवल सभी कार्यक्रमों के लिए एक ही स्थान पर संस्करण स्ट्रिंग को बदलने की आवश्यकता है।

इंस्टॉल के दौरान दौड़ की स्थिति के बारे में चेतावनी

वैसे, अपने पैकेज से अपने पैकेज को आयात न करें जैसा कि यहां एक अन्य उत्तर में सुझाया गया है: यह आपके लिए काम करने लगेगा (क्योंकि आपके पास पहले से ही आपके पैकेज की निर्भरताएं स्थापित हैं), लेकिन यह आपके पैकेज के नए उपयोगकर्ताओं पर कहर बरपाएगा , क्योंकि वे पहले निर्भरता स्थापित किए बिना मैन्युअल रूप से आपके पैकेज को स्थापित करने में सक्षम नहीं होंगे।


1
यह बस यहाँ सबसे अच्छा जवाब है: यदि आप अपने पैकेज से संस्करण प्राप्त करने के लिए setup.py की जरूरत है, तो सबसे अच्छा तरीका निष्पादन का उपयोग करना है।
त्रिपथ

2
execfileवास्तव में अच्छी तरह से काम करता है ... लेकिन (दुख की बात है) पायथन 3 के साथ काम नहीं करता है
मध्यस्थता करता है

9
... ठीक है, पायथन 2 और 3 के with open('mypackage/version.py') as f: exec(f.read())स्थान पर उपयोग के लिए execfile('mypackage/version.py')। (से stackoverflow.com/a/437857/647002 )
medmunds

5
कहर बरपा हिस्सा जरूरी सच नहीं है ... यह केवल कहर बरपा यदि आपका होगा init पैकेज में .py फ़ाइल कोड आयात निर्भरता (प्रत्यक्ष या परोक्ष) है।
पाइक्लर

2
यह उल्लेखनीय है कि django अपने setup.py में __import__ कॉल करता है । क्या '__import__' बनाम 'आयात' इसे सुरक्षित बनाते हैं? यह उन्हें किसी भी समस्या पैदा करने के लिए प्रकट नहीं होता है।
user1978019

33

उदाहरण अध्ययन: mymodule

इस विन्यास की कल्पना करें:

setup.py
mymodule/
        / __init__.py
        / version.py
        / myclasses.py

फिर कुछ सामान्य परिदृश्य की कल्पना करें, जहां आपके पास निर्भरताएं हैं और setup.pyजैसा दिखता है:

setup(...
    install_requires=['dep1','dep2', ...]
    ...)

और एक उदाहरण __init__.py:

from mymodule.myclasses import *
from mymodule.version import __version__

और उदाहरण के लिए myclasses.py:

# these are not installed on your system.
# importing mymodule.myclasses would give ImportError
import dep1
import dep2

समस्या # 1: mymoduleसेटअप के दौरान आयात करना

यदि आपका setup.pyआयात होता है, mymoduleतो सेटअप के दौरान आपको सबसे अधिक संभावना होगी ImportError। यह एक बहुत ही सामान्य त्रुटि है जब आपके पैकेज में निर्भरता होती है। यदि आपके पैकेज में बिल्डरों की तुलना में अन्य निर्भरता नहीं है, तो आप सुरक्षित हो सकते हैं; हालाँकि यह एक अच्छा अभ्यास नहीं है। इसका कारण यह है कि यह भविष्य-प्रमाण नहीं है; कल अपने कोड को कुछ अन्य निर्भरता का उपभोग करने की आवश्यकता है।

समस्या # 2: मेरी कहाँ है __version__?

यदि आप हार्डकोड करते __version__हैं setup.pyतो यह उस संस्करण से मेल नहीं खा सकता है जिसे आप अपने मॉड्यूल में शिप करेंगे। सुसंगत होने के लिए, आप इसे एक स्थान पर रख देंगे और आवश्यकता पड़ने पर इसे उसी स्थान से पढ़ेंगे। उपयोग करने से importआपको समस्या # 1 हो सकती है।

हल: अ ला setuptools

आप चर जोड़ने के लिए एक संयोजन का उपयोग करेंगे open, execऔर एक तानाशाही प्रदान करेंगे exec:

# setup.py
from setuptools import setup, find_packages
from distutils.util import convert_path

main_ns = {}
ver_path = convert_path('mymodule/version.py')
with open(ver_path) as ver_file:
    exec(ver_file.read(), main_ns)

setup(...,
    version=main_ns['__version__'],
    ...)

और mymodule/version.pyसंस्करण को उजागर करें:

__version__ = 'some.semantic.version'

इस तरह, संस्करण को मॉड्यूल के साथ भेज दिया गया है, और आपके पास एक मॉड्यूल को आयात करने की कोशिश कर रहे सेटअप के दौरान समस्याएँ नहीं हैं जिनके पास लापता निर्भरता (अभी तक स्थापित होना) है।


2
यह सबसे उचित समाधान की तरह लगता है क्योंकि यह केवल अनुमत निर्भरताओं पर निर्भर करता है।
डॉगवॉयर

क्या सेटअप वर्जन की अवधारणा को सेटअप से परिभाषित किया गया है जो संस्करण से अलग है ?
चर

16

सबसे अच्छी तकनीक __version__अपने उत्पाद कोड में परिभाषित करना है, फिर इसे वहां से setup.py में आयात करें। यह आपको एक मूल्य देता है जिसे आप अपने रनिंग मॉड्यूल में पढ़ सकते हैं, और इसे परिभाषित करने के लिए केवल एक ही स्थान है।

Setup.py में मान स्थापित नहीं हैं, और setup.py स्थापना के बाद चारों ओर चिपक नहीं करता है।

मैंने क्या किया (उदाहरण के लिए)

# coverage/__init__.py
__version__ = "3.2"


# setup.py
from coverage import __version__

setup(
    name = 'coverage',
    version = __version__,
    ...
    )

अद्यतन (2017): कवरेज ओरेकल संस्करण प्राप्त करने के लिए अब खुद को आयात नहीं करता है। अपने स्वयं के कोड को आयात करने से इसे अनइंस्टॉल किया जा सकता है, क्योंकि आप उत्पाद कोड निर्भरता को आयात करने का प्रयास करेंगे, जो अभी तक स्थापित नहीं हैं, क्योंकि setup.py है जो उन्हें स्थापित करता है।


4
@ इवान: मुझे यकीन नहीं है कि आपको "केवल स्रोत से उस मूल्य को खींचने" के बारे में क्या मिल रहा है। अगर इसमें लगी फाइल __version__किसी तरह से टूट जाती है, तो आपका आयात भी टूट जाएगा। अजगर को नहीं पता कि आपको केवल उन बयानों की व्याख्या कैसे करनी है जो आप चाहते हैं। @pjeby सही है: यदि आपके मॉड्यूल को अन्य मॉड्यूल आयात करने की आवश्यकता है, तो वे अभी तक स्थापित नहीं हो सकते हैं, और यह अराजक होगा। यह तकनीक काम करती है यदि आप सावधान हैं कि आयात अन्य आयातों की लंबी श्रृंखला का दावा नहीं करता है।
नेड बैचेल्ड

1
@Ned Batchelder मुझे पूरा यकीन है कि, अगर आप संस्करण को स्रोत फ़ाइल में किसी भी आयात से पहले रखते हैं और केवल एक 'मॉड्यूल आयात संस्करण से' तो यह स्रोत फ़ाइल के किसी भी अधिक को लेक्स नहीं करेगा, जिसकी उसे आवश्यकता है। इसके अलावा, कौन टूटा हुआ कोड जारी करने जा रहा है? यदि पैकेज को निर्भरता की आवश्यकता है, तो सेटप्टूल का उपयोग करें या वर्ष में बाद में डिस्टुटिल्स 2 की रिहाई की प्रतीक्षा करें।
इवान प्लाइस

15
@ इवान, मुझे क्षमा करें, लेकिन आप आंशिक फ़ाइलों को आयात करने के बारे में गलत हैं। एक लंबे मॉड्यूल के अंत में एक प्रिंट स्टेटमेंट डालने की कोशिश करें, और फ़ाइल में परिभाषित पहले चर को आयात करें। प्रिंट स्टेटमेंट निष्पादित करेगा।
नेड बाचेल्ड

23
मैं इसके लिए गिर गया, लेकिन @pjeby पूरी तरह से सही है: "वैसे, अपने सेटअप को अपने सेटअप से आयात न करें जैसा कि यहां एक अन्य जवाब में सुझाया गया है: यह आपके लिए काम करने लगेगा (क्योंकि आपके पास पहले से ही आपके पैकेज की निर्भरताएं स्थापित हैं ), लेकिन यह आपके पैकेज के नए उपयोगकर्ताओं पर कहर बरपाएगा, क्योंकि वे पहले निर्भरता स्थापित किए बिना मैन्युअल रूप से आपके पैकेज को स्थापित करने में सक्षम नहीं होंगे। " नेड, क्या आप अपने उत्तर के लिए एक चेतावनी जोड़ना चाहेंगे?
डॉ। जन-फिलिप गेर्के

1
@ Jan-PhilipGehrcke की तरह जब मैं PyPI को इस तरह एक सेटअप-थ्रो फ़ाइल अपलोड करता हूं और फिर pip install <packagename>, मुझे निम्न त्रुटि मिलती है ImportError: No module named <packagename>:। कृपया अपने पाठकों को बताएं कि आप इस तरह से सेटअप-इन फ़ाइलों को उन वातावरणों पर नहीं चला सकते जहाँ पैकेज पहले से स्थापित नहीं है!
होब्स

14

आपका प्रश्न थोड़ा अस्पष्ट है, लेकिन मुझे लगता है कि आप जो पूछ रहे हैं, उसे कैसे निर्दिष्ट किया जाए।

आपको इस __version__तरह परिभाषित करने की आवश्यकता है :

__version__ = '1.4.4'

और फिर आप पुष्टि कर सकते हैं कि setup.py आपके द्वारा निर्दिष्ट संस्करण के बारे में जानता है:

% ./setup.py --version
1.4.4

9

मैं इन जवाबों से खुश नहीं था ... को सेटपूल की आवश्यकता नहीं थी, और न ही एक एकल चर के लिए एक अलग मॉड्यूल बनाना था, इसलिए मैं इन के साथ आया।

जब आप सुनिश्चित हों कि मुख्य मॉड्यूल pep8 शैली में है और इस तरह रहेगा:

version = '0.30.unknown'
with file('mypkg/mymod.py') as f:
    for line in f:
        if line.startswith('__version__'):
            _, _, version = line.replace("'", '').split()
            break

यदि आप अतिरिक्त सावधान रहना चाहते हैं और वास्तविक पार्सर का उपयोग करना चाहते हैं:

import ast
version = '0.30.unknown2'
with file('mypkg/mymod.py') as f:
    for line in f:
        if line.startswith('__version__'):
            version = ast.parse(line).body[0].value.s
            break

अगर यह थोड़ा सा बदसूरत है तो सेटअप थ्रू कुछ हद तक एक फेंकने वाला मॉड्यूल है।


अपडेट: मजाकिया तौर पर मैं हाल के वर्षों में इससे दूर चला गया हूं और नामक पैकेज में एक अलग फ़ाइल का उपयोग करना शुरू कर दिया है meta.py। मैंने बहुत सारे मेटा डेटा को वहाँ रखा है जो मैं बार-बार बदलना चाहता हूँ। तो, सिर्फ एक मूल्य के लिए नहीं।


+1। यह अपेक्षाकृत सरल है, संस्करण संख्या को एक स्थान पर रखता है, इसे समाहित करने के लिए एक अलग फ़ाइल की आवश्यकता नहीं है, और सेटअपहोम पर अजगर मॉड्यूल के आयात निर्भरता को लागू नहीं करता है। मैं किसी प्रोग्राम के संदर्भ प्रबंधक के साथ सेटअप-थ्रेड के रूप में अल्पकालिक परेशान नहीं करूंगा।
19:s41oɈ

रेगेक्स का उपयोग करने की तुलना में बहुत अच्छा है, धन्यवाद। आप स्रोत से स्वचालित रूप से भरने के लिए ast.get_docstring()कुछ .split('\n')[0].strip()आदि के साथ भी उपयोग कर सकते हैं description। सिंक में रखने के लिए एक कम चीज
खो दिया

4

अपने स्रोत के पेड़ में एक फ़ाइल बनाएँ, उदाहरण के लिए yourbasedir / yourpackage / _version.py में। उस फ़ाइल में कोड की केवल एक पंक्ति है, जैसे:

__version__ = "1.1.0-r4704"

फिर अपने setup.py में, उस फ़ाइल को खोलें और संस्करण संख्या को इस तरह पार्स करें:

verstr = "अज्ञात"
प्रयत्न:
    verstrline = open ('yourpackage / _version.py', "rt")। read ()
पर्यावरण को छोड़कर:
    # ठीक है, कोई संस्करण फ़ाइल नहीं है।
अन्य:
    VSRE = r "^ __ संस्करण__ = ['\"] ([^' \ "] *) ['\ \"] "
    mo = re.search (VSRE, verstrline, re.M)
    यदि मो:
        verstr = mo.group (1)
    अन्य:
        RuntimeError बढ़ाएं ("आपके पैकेज में संस्करण खोजने में असमर्थ / _version.py")

अंत में, yourbasedir/yourpackage/__init__.pyआयात में _version इस तरह:

__version__ = "अज्ञात"
प्रयत्न:
    _version आयात से _version__
आयात को छोड़कर:
    # हम एक ऐसे पेड़ में चल रहे हैं जिसमें _version.py नहीं है, इसलिए हमें नहीं पता कि हमारा संस्करण क्या है।
    उत्तीर्ण करना

कोड का एक उदाहरण जो ऐसा करता है वह "pyutil" पैकेज है जिसे मैं बनाए रखता हूं। (देखें PyPI या Google खोज - स्टैकओवरफ़्लो मुझे इस उत्तर में एक हाइपरलिंक को शामिल करने से रोक रहा है।)

@pjeby सही है कि आपको अपने पैकेज को अपने स्वयं के सेटअप से आयात नहीं करना चाहिए। जब आप एक नया पायथन इंटरप्रेटर बनाकर और उसमें पहली बार setup.py निष्पादित करके python setup.pyकाम करेंगे, तो यह काम करेगा : लेकिन ऐसे मामले हैं जब यह काम नहीं करेगा। ऐसा इसलिए import youpackageहै क्योंकि "थैरेकेज" नामक निर्देशिका के लिए वर्तमान कार्यशील निर्देशिका को पढ़ने का मतलब नहीं है, इसका मतलब है कि sys.modulesकुंजी "थैरेकेज" के लिए करंट में दिखना और फिर ऐसा न होने पर विभिन्न चीजें करना। इसलिए यह हमेशा काम करता है जब आप ऐसा करते हैं python setup.pyक्योंकि आपके पास एक ताज़ा, खाली है sys.modules, लेकिन यह सामान्य रूप से काम नहीं करता है।

उदाहरण के लिए, क्या होगा अगर py2exe आपके सेटअप को एप्लिकेशन की पैकेजिंग की प्रक्रिया के भाग के रूप में निष्पादित कर रहा है? मैंने इस तरह का एक मामला देखा है जहां py2exe एक पैकेज पर गलत संस्करण संख्या डाल देगा क्योंकि पैकेज से इसका संस्करण नंबर मिल रहा थाimport myownthingइसके setup.py में, लेकिन उस पैकेज का एक अलग संस्करण पहले py2.exe रन के दौरान आयात किया गया था। इसी तरह, क्या होगा अगर सेटपूल, easy_install, वितरित, या distutils2 एक अलग पैकेज स्थापित करने की प्रक्रिया के हिस्से के रूप में आपके पैकेज को बनाने की कोशिश कर रहा है जो कि आप पर निर्भर करता है? फिर आपका पैकेज उस समय आयात करने योग्य है या नहीं, जब उसके सेटअप-थ्रू का मूल्यांकन किया जा रहा है, या क्या पहले से ही आपके पैकेज का कोई संस्करण है, जिसे इस पायथन इंटरप्रेटर के जीवन के दौरान आयात किया गया है, या क्या आपके पैकेज को आयात करने के लिए पहले अन्य पैकेजों की आवश्यकता है , या इसके साइड-इफेक्ट्स हैं, परिणाम बदल सकते हैं। मेरे पास पायथन पैकेजों को पुन: उपयोग करने की कोशिश करने के साथ कई संघर्ष हैं, जो py2.exe और setuptools जैसे उपकरणों के लिए समस्या का कारण बने क्योंकि उनका setup.py पैकेज संस्करण को खोजने के लिए स्वयं ही आयात करता है।

वैसे, यह तकनीक स्वचालित रूप से आपके लिए yourpackage/_version.pyफ़ाइल बनाने के लिए टूल के साथ अच्छी तरह से खेलती है , उदाहरण के लिए अपने संशोधन नियंत्रण इतिहास को पढ़कर और संशोधन नियंत्रण इतिहास में सबसे हाल के टैग के आधार पर एक संस्करण संख्या लिखकर। यहाँ एक उपकरण है जो दरारों के लिए ऐसा करता है: http://tahoe-lafs.org/trac/darcsver/browser/trunk/README.rst और यहाँ एक कोड स्निपेट है जो git के लिए एक ही काम करता है: http: // github .com / वार्नर / अजगर-ECDSA / ब्लॉब / 0ed702a9d4057ecf33eea969b8cf280eaccd89a1 / setup.py # L34


3

यह भी काम करना चाहिए, नियमित अभिव्यक्ति का उपयोग करके और मेटाडेटा फ़ील्ड के आधार पर इस तरह का प्रारूप होना चाहिए:

__fieldname__ = 'value'

अपने सेटअप की शुरुआत में निम्नलिखित का उपयोग करें:

import re
main_py = open('yourmodule.py').read()
metadata = dict(re.findall("__([a-z]+)__ = '([^']+)'", main_py))

उसके बाद, आप अपनी स्क्रिप्ट में मेटाडेटा का उपयोग इस तरह कर सकते हैं:

print 'Author is:', metadata['author']
print 'Version is:', metadata['version']

जैसा कि मैंने ऊपर कहा, बस str.split का उपयोग करें :)
अरुजो

हे भगवान नं। आप पायथन में अजगर को देख रहे हैं? बहुत कम से कम, eval (), बच्चे का उपयोग करें।
आलसी

3
इतना आसान होने पर खराब सलाह की कमी, निष्कासन से बचना चाहिए।
ग्रिंगो सुवे

3

इस तरह की संरचना के साथ:

setup.py
mymodule/
        / __init__.py
        / version.py
        / myclasses.py

जहाँ version.py होता है:

__version__ = 'version_string'

आप इसे setup.py में कर सकते हैं :

import sys

sys.path[0:0] = ['mymodule']

from version import __version__

इससे आपके mymodule / __ init__.py में जो भी निर्भरताएँ हैं, उनके साथ कोई समस्या नहीं होगी


2

एक फ़ाइल आयात करने से बचने के लिए (और इस प्रकार इसके कोड को निष्पादित करने से) कोई इसे पार्स कर सकता है और versionसिंटैक्स ट्री से विशेषता को पुनर्प्राप्त कर सकता है :

# assuming 'path' holds the path to the file

import ast

with open(path, 'rU') as file:
    t = compile(file.read(), path, 'exec', ast.PyCF_ONLY_AST)
    for node in (n for n in t.body if isinstance(n, ast.Assign)):
        if len(node.targets) == 1:
            name = node.targets[0]
            if isinstance(name, ast.Name) and \
                    name.id in ('__version__', '__version_info__', 'VERSION'):
                v = node.value
                if isinstance(v, ast.Str):
                    version = v.s
                    break
                if isinstance(v, ast.Tuple):
                    r = []
                    for e in v.elts:
                        if isinstance(e, ast.Str):
                            r.append(e.s)
                        elif isinstance(e, ast.Num):
                            r.append(str(e.n))
                    version = '.'.join(r)
                    break

यह कोड मॉड्यूल रिटर्न के शीर्ष स्तर पर __version__या VERSIONअसाइनमेंट को खोजने की कोशिश करता है जो स्ट्रिंग मान है। दाईं ओर या तो एक स्ट्रिंग या टपल हो सकता है।


3
यह चतुर और जटिल लग रहा है :) यह सिर्फ एक _version.py एक असाइनमेंट और पार्स के साथ फ़ाइल को खोलने-पढ़ने में str.split युक्त सरल होगा।
ric अरूजो

इसे पोस्ट करने के लिए धन्यवाद। मुझे लगता है कि यह इस स्थिति के लिए बहुत जटिल है, लेकिन यह समझने के लिए बहुत उपयोगी है कि कोई समस्या का सामना कैसे कर सकता है। मुझे पसंद है कि यह संस्करण संख्या को एक स्थान पर रखता है, इसे समाहित करने के लिए एक अलग फ़ाइल की आवश्यकता नहीं होती है, और यह सेटअप स्क्रिप्ट पर अजगर मॉड्यूल के आयात निर्भरता को लागू नहीं करता है।
ʇs37oɈ

2

बिल्ली को त्वचा देने के हजार तरीके हैं - यहाँ मेरा है:

# Copied from (and hacked):
# https://github.com/pypa/virtualenv/blob/develop/setup.py#L42
def get_version(filename):
    import os
    import re

    here = os.path.dirname(os.path.abspath(__file__))
    f = open(os.path.join(here, filename))
    version_file = f.read()
    f.close()
    version_match = re.search(r"^__version__ = ['\"]([^'\"]*)['\"]",
                              version_file, re.M)
    if version_match:
        return version_match.group(1)
    raise RuntimeError("Unable to find version string.")

2

Https://stackoverflow.com/a/12413800 @ gringo-suave से सफाई :

from itertools import ifilter
from os import path
from ast import parse

with open(path.join('package_name', '__init__.py')) as f:
    __version__ = parse(next(ifilter(lambda line: line.startswith('__version__'),
                                     f))).body[0].value.s

2

अब यह स्थूल है और इसे कुछ परिष्कृत करने की आवश्यकता है (यहाँ तक कि pkg_resources में एक खुला सदस्य कॉल भी हो सकता है जो मैं चूक गया), लेकिन मैं बस यह नहीं देखता कि यह क्यों काम नहीं करता है, और न ही किसी ने इसे आज तक सुझाया है (Googling आसपास है) इसे चालू नहीं किया गया) ... ध्यान दें कि यह पायथन 2.x है, और इसके लिए pkg_resource (sigh) की आवश्यकता होगी:

import pkg_resources

version_string = None
try:
    if pkg_resources.working_set is not None:
        disto_obj = pkg_resources.working_set.by_key.get('<my pkg name>', None)
        # (I like adding ", None" to gets)
        if disto_obj is not None:
            version_string = disto_obj.version
except Exception:
    # Do something
    pass

2

हम अपने पैकेज के बारे में मेटा जानकारी रखना चाहते थे pypackageryमें__init__.py , लेकिन नहीं, क्योंकि यह तीसरे पक्ष के निर्भरता के रूप में पीजे Eby पहले से ही (अपने जवाब और दौड़ हालत के बारे में चेतावनी दिखाई) ने बताया सका।

हमने इसे एक अलग मॉड्यूल बनाकर हल किया है pypackagery_meta.pyजिसमें केवल मेटा जानकारी है:

"""Define meta information about pypackagery package."""

__title__ = 'pypackagery'
__description__ = ('Package a subset of a monorepo and '
                   'determine the dependent packages.')
__url__ = 'https://github.com/Parquery/pypackagery'
__version__ = '1.0.0'
__author__ = 'Marko Ristin'
__author_email__ = 'marko.ristin@gmail.com'
__license__ = 'MIT'
__copyright__ = 'Copyright 2018 Parquery AG'

इसके बाद मेटा जानकारी आयात की गई packagery/__init__.py:

# ...

from pypackagery_meta import __title__, __description__, __url__, \
    __version__, __author__, __author_email__, \
    __license__, __copyright__

# ...

और अंत में इसका इस्तेमाल किया setup.py:

import pypackagery_meta

setup(
    name=pypackagery_meta.__title__,
    version=pypackagery_meta.__version__,
    description=pypackagery_meta.__description__,
    long_description=long_description,
    url=pypackagery_meta.__url__,
    author=pypackagery_meta.__author__,
    author_email=pypackagery_meta.__author_email__,
    # ...
    py_modules=['packagery', 'pypackagery_meta'],
 )

आपको सेटअप तर्क के pypackagery_metaसाथ अपने पैकेज में शामिल होना चाहिए py_modules। अन्यथा, आप इसे इंस्टॉलेशन पर आयात नहीं कर सकते क्योंकि पैक किए गए वितरण में इसकी कमी होगी।


1

सरल और सीधे, source/package_name/version.pyनिम्नलिखित सामग्रियों के साथ एक फ़ाइल बनाएं :

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
__version__ = "2.6.9"

फिर, आपकी फ़ाइल पर source/package_name/__init__.py, आप अन्य लोगों के उपयोग के लिए संस्करण आयात करते हैं:

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
from .version import __version__

अब, आप इसे लगा सकते हैं setup.py

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
import re
import sys

try:
    filepath = 'source/package_name/version.py'
    version_file = open( filepath )
    __version__ ,= re.findall( '__version__ = "(.*)"', version_file.read() )

except Exception as error:
    __version__ = "0.0.1"
    sys.stderr.write( "Warning: Could not open '%s' due %s\n" % ( filepath, error ) )

finally:
    version_file.close()

अजगर के साथ इस परीक्षण किया गया 2.7, 3.3, 3.4, 3.5, 3.6और 3.7लिनक्स, Windows और मैक ओएस पर। मैंने अपने पैकेज पर इस्तेमाल किया जिसमें सभी थ्रेस प्लेटफॉर्म के लिए इंटीग्रेशन और यूनिट टेस्ट हैं। आप परिणाम देख सकते हैं .travis.ymlऔर appveyor.ymlयहाँ:

  1. https://travis-ci.org/evandrocoan/debugtools/builds/527110800
  2. https://ci.appveyor.com/project/evandrocoan/pythondebugtools/builds/24245446

एक वैकल्पिक संस्करण संदर्भ प्रबंधक का उपयोग कर रहा है:

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
import re
import sys

try:
    filepath = 'source/package_name/version.py'

    with open( filepath ) as file:
        __version__ ,= re.findall( '__version__ = "(.*)"', file.read() )

except Exception as error:
    __version__ = "0.0.1"
    sys.stderr.write( "Warning: Could not open '%s' due %s\n" % ( filepath, error ) )

आप codecsपायथन 2.7और दोनों पर यूनिकोड त्रुटियों को संभालने के लिए मॉड्यूल का उपयोग कर सकते हैं3.6

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
import re
import sys
import codecs

try:
    filepath = 'source/package_name/version.py'

    with codecs.open( filepath, 'r', errors='ignore' ) as file:
        __version__ ,= re.findall( '__version__ = "(.*)"', file.read() )

except Exception as error:
    __version__ = "0.0.1"
    sys.stderr.write( "Warning: Could not open '%s' due %s\n" % ( filepath, error ) )

यदि आप पायथन सी एक्सटेंशन का उपयोग करके C / C ++ में 100% Python मॉड्यूल लिख रहे हैं, तो आप एक ही काम कर सकते हैं, लेकिन Python के बजाय C / C ++ का उपयोग कर सकते हैं।

इस मामले पर, निम्नलिखित बनाएँ setup.py:

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
import re
import sys
import codecs
from setuptools import setup, Extension

try:
    filepath = 'source/version.h'

    with codecs.open( filepath, 'r', errors='ignore' ) as file:
        __version__ ,= re.findall( '__version__ = "(.*)"', file.read() )

except Exception as error:
    __version__ = "0.0.1"
    sys.stderr.write( "Warning: Could not open '%s' due %s\n" % ( filepath, error ) )

setup(
        name = 'package_name',
        version = __version__,

        package_data = {
                '': [ '**.txt', '**.md', '**.py', '**.h', '**.hpp', '**.c', '**.cpp' ],
            },

        ext_modules = [
            Extension(
                name = 'package_name',
                sources = [
                    'source/file.cpp',
                ],
                include_dirs = ['source'],
            )
        ],
    )

जो संस्करण को फ़ाइल से पढ़ता है version.h:

const char* __version__ = "1.0.12";

लेकिन, फ़ाइल MANIFEST.inको शामिल करने के लिए बनाना न भूलें version.h:

include README.md
include LICENSE.txt

recursive-include source *.h

और इसे मुख्य एप्लिकेशन में एकीकृत किया गया है:

#include <Python.h>
#include "version.h"

// create the module
PyMODINIT_FUNC PyInit_package_name(void)
{
    PyObject* thismodule;
    ...

    // https://docs.python.org/3/c-api/arg.html#c.Py_BuildValue
    PyObject_SetAttrString( thismodule, "__version__", Py_BuildValue( "s", __version__ ) );

    ...
}

संदर्भ:

  1. अजगर खुली फ़ाइल त्रुटि
  2. सी एपीआई से एक पायथन मॉड्यूल में एक वैश्विक परिभाषित करें
  3. सेटटॉपल्स / डिस्ट्रीब्यूशन के साथ पैकेज डेटा कैसे शामिल करें?
  4. https://github.com/lark-parser/lark/blob/master/setup.py#L4
  5. एक ही नाम के साथ सेटपूल पैकेज और ext_modules कैसे उपयोग करें?
  6. क्या पैकेज डेटा के भाग के रूप में डिस्टिल्ट (सेटअप एरोकोम) का उपयोग करके उपनिर्देशिका को शामिल करना संभव है?

1

सर्वर के लिए पैकेज की तैनाती और सूचकांक पैकेज के लिए नामकरण सम्मेलन दर्ज करें:

पाइप डायनामिक संस्करण रूपांतरण के लिए उदाहरण:

  • जीत:

    • test_pkg-1.0.0-cp36-cp36m-win_amd64.whl
    • test_pkg-1.0.0-py3.6 जीत-amd64.egg
  • मैक:

    • test_pkg-1.0.0-py3.7-macosx-10.12-x86_64.egg
    • test_pkg-1.0.0-py3.7-macosx-10.12-x86_64.whl
  • linux:
    • test_pkg-1.0.0-cp36-cp36m-linux_x86_64.whl
from setuptools_scm import get_version

def _get_version():

     dev_version = str(".".join(map(str, str(get_version()).split("+")[0]\
            .split('.')[:-1])))

    return dev_version

सैंपल सेटअप को खोजें जीआईटी कमिट से डायनेमिक पाइप संस्करण का मिलान करता है

setup(
    version=_get_version(),
    name=NAME,
    description=DESCRIPTION,
    long_description=LONG_DESCRIPTION,
    classifiers=CLASSIFIERS,

# add few more for wheel wheel package ...conversion

)

0

मैं नीचे के रूप में एक पर्यावरण चर का उपयोग कर रहा हूं

संस्करण = 0.0.0 पायथन सेटअप ओरोमोडिटी sdist bdist_wheel

Setup.py में


import os

setup(
    version=os.environ['VERSION'],
    ...
)

पैकर संस्करण के साथ स्थिरता की जांच के लिए, मैं नीचे स्क्रिप्ट का उपयोग कर रहा हूं।

PKG_VERSION=`python -c "import pkg; print(pkg.__version__)"`
if [ $PKG_VERSION == $VERSION ]; then
    python setup.py sdist bdist_wheel
else
    echo "Package version differs from set env variable"
fi
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.