सेटअपहोम के साथ गैर-पायथन फाइलें शामिल हैं


200

मैं setup.pyएक फाइल को कैसे शामिल करूं जो कोड का हिस्सा नहीं है? (विशेष रूप से, यह एक लाइसेंस फ़ाइल है, लेकिन यह किसी भी अन्य चीज हो सकती है।)

मैं फ़ाइल के स्थान को नियंत्रित करने में सक्षम होना चाहता हूं। मूल स्रोत फ़ोल्डर में, फ़ाइल पैकेज की जड़ में है। (यानी सबसे ऊपर के समान स्तर पर __init__.py।) मैं चाहता हूं कि यह वहीं रहे जब पैकेज स्थापित हो, ऑपरेटिंग सिस्टम की परवाह किए बिना। मैं उसको कैसे करू?


आप इस समय कैसे करते हैं? आपका पिछला प्रश्न इंगित करता है कि आप लाइसेंस फ़ाइल को जोड़ने के तरीके से परिचित हैं, तो आपका कोड क्या है जो "काम नहीं करता है"?
साइलेंटगॉस्ट

2
data_files = [('', ['lgpl2.1_license.txt',]),]इसे Python26 फ़ोल्डर में रखता है।
राम रचम

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

धन्यवाद इवान। हालांकि, मैं सेटपूल के उपयोग से पूरी तरह से ठीक हूं, क्योंकि यह बहुत प्रचलित है।
राम रचूम

जवाबों:


224

संभवतः ऐसा करने का सबसे अच्छा तरीका setuptools package_dataनिर्देश का उपयोग करना है । इसका मतलब इसके बजाय setuptools(या distribute) का उपयोग करना है distutils, लेकिन यह एक बहुत ही सहज "अपग्रेड" है।

यहाँ एक पूर्ण (लेकिन अप्रयुक्त) उदाहरण दिया गया है:

from setuptools import setup, find_packages

setup(
    name='your_project_name',
    version='0.1',
    description='A description.',
    packages=find_packages(exclude=['ez_setup', 'tests', 'tests.*']),
    package_data={'': ['license.txt']},
    include_package_data=True,
    install_requires=[],
)

उन विशिष्ट पंक्तियों पर ध्यान दें जो यहां महत्वपूर्ण हैं:

package_data={'': ['license.txt']},
include_package_data=True,

package_dataएक dictपैकेज के नाम (खाली = सभी संकुल) प्रतिमानों की सूची के लिए (globs शामिल कर सकते हैं) के। उदाहरण के लिए, यदि आप अपने पैकेज में केवल फाइलें निर्दिष्ट करना चाहते हैं, तो आप वह भी कर सकते हैं:

package_data={'yourpackage': ['*.txt', 'path/to/resources/*.txt']}

यहाँ समाधान निश्चित रूप से विस्तार के साथ आपकी गैर- फ़ाइलों का नाम बदलने के लिए नहीं है ।py.py

अधिक जानकारी के लिए इयान बेकिंग की प्रस्तुति देखें ।

अद्यतन: एक और [बेहतर] दृष्टिकोण

एक अन्य दृष्टिकोण जो अच्छी तरह से काम करता है यदि आप स्रोत वितरण की सामग्री को नियंत्रित करना चाहते हैं ( sdist) और पैकेज के बाहर की फाइलें (जैसे शीर्ष-स्तरीय निर्देशिका) एक MANIFEST.inफ़ाइल जोड़ना है । इस फ़ाइल के प्रारूप के लिए पायथन प्रलेखन देखें ।

इस प्रतिक्रिया को लिखने के बाद से, मैंने पाया है कि MANIFEST.inआम तौर पर आपके स्रोत वितरण ( tar.gz) में आपकी ज़रूरी फाइलों के वितरण के लिए एक कम निराशाजनक दृष्टिकोण है ।

उदाहरण के लिए, यदि आप requirements.txtशीर्ष-स्तर से शामिल करना चाहते हैं, तो शीर्ष-स्तर "डेटा" निर्देशिका को पुन: शामिल करें:

include requirements.txt
recursive-include data *

फिर भी, इन फ़ाइलों को साइट-पैकेज के अंदर पैकेज के फ़ोल्डर में स्थापित करने के लिए कॉपी करने के लिए, आपको फ़ंक्शन को आपूर्ति include_package_data=Trueकरने की आवश्यकता होगी setup()। अधिक जानकारी के लिए गैर-कोड फ़ाइलें जोड़ना देखें ।


5
package_data भी प्योर डिस्टुटिल्स सेटअप स्क्रिप्ट के लिए उपलब्ध है जो कि पायथन 2.3 के बाद से है।
12ric Araujo

15
यह उत्तर समझदार लगता है, लेकिन मेरे लिए काम नहीं करता है। चूंकि package_data बहुत ही अविश्वसनीय रूप से अविश्वसनीय है (दोनों चरणों में sdist में फ़ाइलों को जोड़ने और उन्हें स्थापित करने के लिए MANIFEST.in और setup.py के समन्वय की आवश्यकता है) और इस उत्तर के लेखक ने नोट किया कि यह "परीक्षण नहीं" है, क्या कोई भी कर सकता है। और पुष्टि करें कि क्या यह उनके लिए काम करता है? मेरी LICENSE फाइल sdist में सम्‍मिलित है, लेकिन जब मैं "python setup.py install" और न ही "pip install Package" चलाता हूं, तो इंस्टॉल नहीं होता
जोनाथन हार्टले

11
इयान बेकिंग की प्रस्तुति केवल यह दिखाती है कि पैकेज के भीतर मौजूद फ़ाइलों के लिए पैकेज डेटा कैसे स्थापित किया जाए। मेरी LICENSE फ़ाइल मेरे प्रोजेक्ट के शीर्ष स्तर पर है, अर्थात किसी भी पैकेज में नहीं। क्या मैं अभी भी package_data का उपयोग कर सकता हूं? Data_files का उपयोग करना एक गैर-स्टार्टर है, क्योंकि यह फाइलों को सिस्टम-वाइड लोकेशन में रखता है। मेरे प्रोजेक्ट से संबद्ध नहीं है, और इसे बदतर बनाने के लिए, मैं एक ही sdist से "setup.py इंस्टॉल" या "पाइप इंस्टॉल" चलाने के आधार पर स्थान बदलता है।
जोनाथन हार्टले

8
मैं अनुमान लगा रहा हूं कि मेरे लिए काम नहीं करने का कारण यह है कि फाइल किसी भी पैकेज में नहीं है - यह रिपॉजिटरी के शीर्ष स्तर में एक LICENSE फाइल है, और इसलिए 'package_data' का उपयोग करके स्थापित नहीं किया जा सकता है
जोनाथन हार्टले

7
यह जवाब मेरे काम नहीं आता। अतिरिक्त फ़ाइलों को टारबॉल में नहीं डाला जा रहा है ...
lpapp

44

जो आप वर्णन कर रहे हैं उसे पूरा करने के लिए दो कदम उठाने होंगे ...

  • फ़ाइल को स्रोत टारबॉल में जोड़ने की आवश्यकता है
  • सेटअप फ़ाइल को डेटा फ़ाइल को स्रोत पथ पर स्थापित करने के लिए संशोधित करने की आवश्यकता है

चरण 1: फ़ाइल को स्रोत टारबॉल में जोड़ने के लिए, इसे मैनिफ़ेस्ट में शामिल करें

उस फ़ोल्डर में एक MANIFEST टेम्प्लेट बनाएं जिसमें setup.py शामिल है

मैनिफेस्ट मूल रूप से एक टेक्स्ट फाइल है जिसमें उन सभी फाइलों की सूची होती है, जिन्हें स्रोत टारबॉल में शामिल किया जाएगा।

यहाँ मेरी परियोजना के लिए मैनिफ़ेस्ट कैसा दिखता है:

  • changelog.txt
  • install.txt
  • license.txt
  • pypreprocessor.py
  • README.txt
  • setup.py
  • test.py
  • TODO.txt

नोट: जबकि sdist कुछ फ़ाइलों को स्वचालित रूप से जोड़ता है , मैं यह स्पष्ट रूप से निर्दिष्ट करना पसंद करता हूं कि यह क्या और क्या नहीं करता है, यह भविष्यवाणी करने के बजाय सुनिश्चित करें।

चरण 2: डेटा फ़ाइल को स्रोत फ़ोल्डर में स्थापित करने के लिए, setup.py संशोधित करें

चूंकि आप स्रोत इंस्टॉल फ़ोल्डर में डेटा फ़ाइल (LICENSE.txt) जोड़ना चाहते हैं, तो आपको स्रोत इंस्टॉल पथ से मिलान करने के लिए डेटा इंस्टॉल पथ को संशोधित करना होगा। यह आवश्यक है क्योंकि, डिफ़ॉल्ट रूप से, डेटा फ़ाइलों को स्रोत फ़ाइलों की तुलना में एक अलग स्थान पर स्थापित किया जाता है।

स्रोत स्थापित dir से मेल खाने के लिए डेटा इंस्टॉल dir को संशोधित करने के लिए ...

के साथ distirils से स्थापित dir जानकारी खींचें:

from distutils.command.install import INSTALL_SCHEMES

स्रोत इंस्‍टॉल dir से मिलान करने के लिए डेटा इंस्‍टॉल dir को संशोधित करें:

for scheme in INSTALL_SCHEMES.values():
    scheme['data'] = scheme['purelib']

और, डेटा फ़ाइल और स्थान को सेटअप में जोड़ें ():

data_files=[('', ['LICENSE.txt'])]

नोट: ऊपर दिए गए चरणों को किसी भी विस्तार पुस्तकालयों की आवश्यकता के बिना एक मानक तरीके से वर्णित किए गए कार्यों को पूरा करना चाहिए।


10
MANIFEST केवल नियंत्रण फ़ाइलों को स्रोत टारबॉल (sdist द्वारा निर्मित) में शामिल करता है। वहाँ सूचीबद्ध फ़ाइलें स्थापित नहीं होंगी।
डेविड कर्नप्यू 7

@ मुझे पता ही नहीं चला कि मैं अपने पहले दृष्टिकोण से कितना दूर था। मैंने किसी भी अतिरिक्त तृतीय-पक्ष पुस्तकालयों की आवश्यकता के बिना सवाल पूछने के लिए सही होने के उत्तर को अपडेट किया है।
इवान प्लाइस

3
@ @Ric कोई विशेष कारण? और, क्या आपके पास एक व्यवहार्य इंस्टॉलर विकल्प है जिसे काम करने के लिए 3 पार्टी पैकेज (जैसे setup_tools) की आवश्यकता नहीं है। मैंने सेटप्टूल से अधिक डिस्टिलिट्स को चुना क्योंकि यह अजगर के एक वेनिला इंस्टॉल के साथ शामिल है और मैं PYPI के लिए मॉड्यूल का निर्माण कर रहा था। अब इसे डिस्टुटिल्स 2 का उपयोग करने का एक बेहतर तरीका होना चाहिए लेकिन मैंने काफी समय में अजगर को नहीं छुआ है, इसलिए मुझे नहीं पता होगा कि कैसे। जब से आप डिस्टुटिल्स 2 के बारे में जानकार लगते हैं, मुझे लगता है कि इससे हमें उचित डिस्टुटिल्स 2 विकल्प का लाभ मिलेगा।
इवान प्लाइस

6
जैसा कि अन्य थ्रेड्स में उल्लेख किया गया है, package_dataअगर फ़ाइल पैकेज में नहीं है तो काम नहीं करता है।
ग्रिंगो सुवे

2
@ AricAraujo: इस समाधान का उपयोग करना बुरा नहीं है क्योंकि कोई अन्य तरीका नहीं है। यह एक खराब डिस्टिल्स डिज़ाइन है - यह सच है। लेकिन यह वास्तविक रूप से सार्वजनिक एपीआई है जो कभी नहीं बदलेगा, क्योंकि यह कई चीजों को तोड़ देगा। चलो आशा करते हैं कि distutils2 बेहतर अनुशंसित तरीके प्रदान करेगा।
अनातोली टेकटोनिक


7

मैं एक प्रश्न के लिए एक टिप्पणी पोस्ट करना चाहता था, लेकिन मुझे ऐसा करने के लिए पर्याप्त प्रतिष्ठा नहीं मिली>>।>

यहाँ मेरे लिए क्या काम किया (डॉक्स का जिक्र करने के बाद इसके साथ आया):

package_data={
    'mypkg': ['../*.txt']
},

include_package_data: False

अंतिम पंक्ति मेरे लिए भी काफी अजीब थी, (आप इस खोजशब्द तर्क को भी छोड़ सकते हैं - यह वही काम करता है)।

यह क्या करता है यह आपके शीर्ष-स्तरीय या रूट निर्देशिका में सभी पाठ फ़ाइलों की प्रतिलिपि बनाता है (पैकेज से एक स्तर ऊपर जो mypkgआप वितरित करना चाहते हैं)।

उम्मीद है की यह मदद करेगा!


मैं एक रास्ता नहीं बनाने की तलाश कर रहा था MANIFEST.in, यह मेरे लिए काम करता है। अंतिम पंक्ति मेरे लिए भी महत्वपूर्ण थी। मेरी पंक्तियाँ थींinclude_package_data=False, package_data={ "": ["../CHANGELOG.md"] },
मेंढक

7

स्टेप 1:MANIFEST.in सेटअपफ्रीड के साथ एक ही फोल्डर में एक फाइल बनाएं

चरण 2: उन फ़ाइलों के सापेक्ष पथ शामिल करें जिन्हें आप जोड़ना चाहते हैंMANIFEST.in

include README.rst
include docs/*.txt
include funniest/data.json

चरण 3: इन फाइलों को साइट-पैकेज में कॉपी करने के include_package_data=Trueलिए setup()फ़ंक्शन में सेट करें

संदर्भ यहाँ है।


6

यह 2019 है, और यहां वह है जो काम कर रहा है - यहां और वहां सलाह के बावजूद, मैंने जो इंटरनेट पर आधे रास्ते पर दस्तावेज पाया है, वह setuptools_scmविकल्प के रूप में पारित किया गया है setuptools.setup। इसमें आपके वीसीएस पर संस्करणित कोई भी डेटा फ़ाइलें शामिल होंगी, चाहे वह गिट हो या कोई अन्य, पहिया पैकेज हो, और उन फ़ाइलों को लाने के लिए गिट रिपॉजिटरी से "पाइप इंस्टॉल" करेगा।

इसलिए, मैंने इन दोनों लाइनों को "setup.py" पर सेटअप कॉल में जोड़ा। कोई अतिरिक्त इंस्टॉल या आयात आवश्यक नहीं:

    setup_requires=['setuptools_scm'],
    include_package_data=True,

Package_data को मैन्युअल रूप से या MANIFEST.in फ़ाइल में सूचीबद्ध करने की आवश्यकता नहीं है - यदि यह संस्करणित है, तो इसे पैकेज में शामिल किया गया है। "Setuptools_scm" पर डॉक्स ने प्रतिबद्ध स्थिति से एक संस्करण संख्या बनाने पर जोर दिया, और डेटा फ़ाइलों को जोड़ने के वास्तव में महत्वपूर्ण हिस्से की उपेक्षा की। (अगर मेरे इंटरमीडिएट व्हील फाइल का नाम "* 0.2.2.dev45 + g3495a1f" है, तो मैं कम परवाह नहीं कर सकता हूं या हार्डकोड संस्करण संख्या "0.3.0dev0" का उपयोग करूंगा - जिसमें मैंने टाइप किया है - लेकिन प्रोग्राम से बचने के लिए महत्वपूर्ण फाइलें छोड़ना पीछे काम कुछ महत्वपूर्ण है)


5

Setup.py में setup (:

setup(
   name = 'foo library'
   ...
  package_data={
   'foolibrary.folderA': ['*'],     # All files from folder A
   'foolibrary.folderB': ['*.txt']  #All text files from folder B
   },

1
यह वास्तव में ओपी के लक्ष्य को पूरा करने की दिशा में कुछ नहीं करता है। आप जो कुछ भी लिखते हैं package_dataउस पर कोई प्रभाव नहीं पड़ता setup.py installहै, जब तक कि आप खुद ही इंस्टॉल कमांड को संशोधित नहीं करते हैं। जब तक कि वे फाइलें पैकेज डायरेक्टरी के अंतर्गत न हों, जो आमतौर पर ऐसी चीज होती है जिससे आप बचना चाहते हैं।
wvxvw

3

यहाँ एक सरल उत्तर है जो मेरे लिए काम करता है।

सबसे पहले, ऊपर एक पायथन देव की टिप्पणी के अनुसार, सेटपूल की आवश्यकता नहीं है:

package_data is also available to pure distutils setup scripts 
since 2.3.  Éric Araujo

यह बहुत अच्छा है क्योंकि आपके पैकेज पर सेटप्टूल की आवश्यकता डालने का मतलब है कि आपको इसे भी स्थापित करना होगा। संक्षेप में:

from distutils.core import setup

setup(
    # ...snip...
    packages          = ['pkgname'],
    package_data      = {'pkgname': ['license.txt']},
)

1
यह शिकायत करेगा कि निर्देशिका pkgameमौजूद नहीं है
एंथनी काँग

1

मैं बस कुछ चीज़ों का पालन करना चाहता था जो मैंने सेंटोस 6 पर पायथन 2.7 के साथ काम करते हुए पाया। पैकेज_डेटा या डेटा_फाइल्स को जोड़ना जैसा कि ऊपर उल्लेख किया गया था, मेरे लिए काम नहीं किया। मैंने उन फ़ाइलों के साथ एक MANIFEST.IN जोड़ा, जो मैं चाहता था कि गैर-पायथन फ़ाइलों को टैरबॉल में डाल दें, लेकिन उन्हें आरपीएम के माध्यम से लक्ष्य मशीन पर स्थापित नहीं किया।

अंत में, मैं सेटअप / सेटपूल में "विकल्पों" का उपयोग करके अपने समाधान में फ़ाइलों को प्राप्त करने में सक्षम था। विकल्प फ़ाइलें आपको सेटअप फ़ाइल से युक्ति के विभिन्न अनुभागों को संशोधित करने देती हैं। निम्नलिखित नुसार।

from setuptools import setup


setup(
    name='theProjectName',
    version='1',
    packages=['thePackage'],
    url='',
    license='',
    author='me',
    author_email='me@email.com',
    description='',
    options={'bdist_rpm': {'install_script': 'filewithinstallcommands'}},
)

फ़ाइल - MANIFEST.in:

include license.txt

फ़ाइल - filewithinstallcommands:

mkdir -p $RPM_BUILD_ROOT/pathtoinstall/
#this line installs your python files
python setup.py install -O1 --root=$RPM_BUILD_ROOT --record=INSTALLED_FILES
#install license.txt into /pathtoinstall folder
install -m 700 license.txt $RPM_BUILD_ROOT/pathtoinstall/
echo /pathtoinstall/license.txt >> INSTALLED_FILES

-12

पता लगा एक समाधान: मैं अपने नाम दिया lgpl2.1_license.txtकरने के लिए lgpl2.1_license.txt.py, और पाठ के आसपास कुछ ट्रिपल कोट्स डाल दिया। अब मुझे data_filesविकल्प का उपयोग करने की आवश्यकता नहीं है और न ही किसी पूर्ण पथ को निर्दिष्ट करने की। इसे पायथन मॉड्यूल बनाना बदसूरत है, मुझे पता है, लेकिन मैं इसे पूर्ण पथ निर्दिष्ट करने की तुलना में कम बदसूरत मानता हूं।


7
मेरी पोस्ट देखें यह बदसूरत होना नहीं है। नेट पर एक अच्छा उदाहरण खोजना मुश्किल है क्योंकि सेटअप पैकेजों के लिए अच्छा प्रलेखन खोजना मुश्किल है।
इवान प्लाइस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.