setuptools: पैकेज डेटा फ़ोल्डर स्थान


94

मैं अपने अजगर पैकेज को वितरित करने के लिए सेटप्टूल का उपयोग करता हूं। अब मुझे अतिरिक्त डेटाफाइल्स वितरित करने की आवश्यकता है।

सेटटॉपूल डॉक्यूमेंटेशन से मैंने जो कुछ भी इकट्ठा किया है, उससे मुझे पैकेज डायरेक्टरी के अंदर अपनी डेटा फाइलें रखने की जरूरत है। हालाँकि, मैं अपने डेटाफाइल्स को रूट डायरेक्टरी में उपनिर्देशिका के अंदर रखना चाहूंगा।

मैं क्या बचना चाहूंगा:

/ #root
|- src/
|  |- mypackage/
|  |  |- data/
|  |  |  |- resource1
|  |  |  |- [...]
|  |  |- __init__.py
|  |  |- [...]
|- setup.py

इसके बजाय मैं क्या करना चाहूंगा:

/ #root
|- data/
|  |- resource1
|  |- [...]
|- src/
|  |- mypackage/
|  |  |- __init__.py
|  |  |- [...]
|- setup.py

मैं बस इतने सारे उपनिर्देशिकाओं के साथ सहज महसूस नहीं करता, अगर यह आवश्यक नहीं है। मैं एक कारण खोजने में विफल रहता हूं, क्यों मुझे फाइलों को पैकेज निर्देशिका के अंदर रखना है। यह बहुत से नेस्टेड उपनिर्देशिका IMHO के साथ काम करने के लिए बोझिल है। या कोई अच्छा कारण है जो इस प्रतिबंध को सही ठहराएगा?


8
मैंने संसाधनों (डॉक्स, चित्र, आदि) को वितरित करने के लिए 'data_files' का उपयोग करने के बारे में एक समान प्रश्न पूछा: stackoverflow.com/questions/5192386/… ... और (दो) दोनों प्रतिक्रियाओं ने कहा कि इसके बजाय 'package_data' का उपयोग करें। अब मैं पैकेज डेटा का उपयोग कर रहा हूं, लेकिन इसका मतलब है कि मुझे अपने डेटा और डॉक्स को अपने पैकेज के अंदर रखना होगा, अर्थात मेरे स्रोत कोड के बीच मिश्रित होना चाहिए। मुझे यह नापसंद है। अपने स्रोत को पकड़ते समय, मैं न केवल उस वर्ग परिभाषा को खोजता हूं जिसे मैं खोज रहा हूं, बल्कि मेरे RST, HTML और मध्यवर्ती फ़ाइलों के भीतर दर्जनों उल्लेख भी उन्हें मिलते हैं। :-(
जोनाथन हार्टले

2
मुझे पता है कि यह प्रतिक्रिया बहुत देर हो चुकी है, @JonathanHartley, लेकिन आप किसी भी डायरेक्टरी को __init__.pyफाइल जोड़कर "पैकेज" बना सकते हैं , भले ही वह फाइल खाली क्यों न हो। तो आप __init__.pyएक पैकेज की तरह दिखने के लिए एक खाली फ़ाइल के साथ एक डेटा निर्देशिका को अलग रख सकते हैं । कि अपने स्रोत के पेड़ के भीतर से उन्हें लेने से जीआरईपी रखना चाहिए, लेकिन यह अभी भी अजगर और इसके निर्माण उपकरण द्वारा एक पैकेज के रूप में पहचाना जाएगा।
djj

@dhj एक दिलचस्प विचार, धन्यवाद।
जोनाथन हार्टले

4
उस दृष्टिकोण के साथ @dhj एकमात्र समस्या यह है कि आपको लगता है कि आपने 'डेटा' नामक एक पैकेज स्थापित किया है। यदि आपके द्वारा इंस्टॉल किया गया कोई अन्य पैकेज उसी तरह डेटा पैकेज करने की कोशिश करता है, तो आपके पास दो परस्पर विरोधी 'डेटा' पैकेज स्थापित होंगे।
पैर की उंगलियों

जवाबों:


111

विकल्प 1: पैकेज डेटा के रूप में स्थापित करें

अपने पायथन पैकेज के रूट के अंदर डेटा फ़ाइलों को रखने का मुख्य लाभ यह है कि यह आपको इस बारे में चिंता करने से बचने देता है कि फ़ाइलें उपयोगकर्ता के सिस्टम पर कहाँ रहेंगी, जो कि विंडोज़, मैक, लिनक्स, कुछ मोबाइल प्लेटफ़ॉर्म, या एग के अंदर हो सकती हैं। आप हमेशा निर्देशिका पा सकते हैंdata अपने पायथन पैकेज रूट के सापेक्ष , कोई फर्क नहीं पड़ता कि यह कहाँ या कैसे स्थापित है।

उदाहरण के लिए, अगर मेरे पास एक परियोजना लेआउट है जैसे:

project/
    foo/
        __init__.py
        data/
            resource1/
                foo.txt

आप __init__.pyडेटा फ़ाइल के लिए एक निरपेक्ष पथ का पता लगाने के लिए एक फ़ंक्शन जोड़ सकते हैं :

import os

_ROOT = os.path.abspath(os.path.dirname(__file__))
def get_data(path):
    return os.path.join(_ROOT, 'data', path)

print get_data('resource1/foo.txt')

आउटपुट:

/Users/pat/project/foo/data/resource1/foo.txt

परियोजना के बाद एक अंडे के रूप में स्थापित करने के लिए रास्ता dataबदल जाएगा, लेकिन कोड को बदलने की जरूरत नहीं है:

/Users/pat/virtenv/foo/lib/python2.6/site-packages/foo-0.0.0-py2.6.egg/foo/data/resource1/foo.txt

विकल्प 2: निश्चित स्थान पर स्थापित करें

विकल्प आपके डेटा को पायथन पैकेज के बाहर रखना होगा और फिर या तो:

  1. का स्थान है dataकॉन्फ़िगरेशन फ़ाइल, कमांड लाइन तर्क या के माध्यम पारित
  2. अपने पायथन कोड में स्थान एम्बेड करें।

यह बहुत कम वांछनीय है यदि आप अपनी परियोजना को वितरित करने की योजना बनाते हैं। यदि आप वास्तव में ऐसा करना चाहते हैं, तो आप dataटापल्स की सूची में पास करके फ़ाइलों के प्रत्येक समूह के लिए गंतव्य को निर्दिष्ट करके लक्ष्य प्रणाली पर अपनी पसंद के अनुसार कहीं भी स्थापित कर सकते हैं :

from setuptools import setup
setup(
    ...
    data_files=[
        ('/var/data1', ['data/foo.txt']),
        ('/var/data2', ['data/bar.txt'])
        ]
    )

अद्यतित : एक शेल फ़ंक्शन का उदाहरण पुन: प्राप्त करने के लिए Pyreon फ़ाइलों को संक्षिप्त करें:

atlas% function grep_py { find . -name '*.py' -exec grep -Hn $* {} \; }
atlas% grep_py ": \["
./setup.py:9:    package_data={'foo': ['data/resource1/foo.txt']}

7
स्थिति के साथ आने में मेरी मदद करने के लिए बहुत बहुत धन्यवाद। इसलिए मैं आपको (और बाकी सभी) सुझाव के रूप में package_data का उपयोग करके खुश हूं। हालाँकि: क्या यह केवल मुझे है जो अपने पैकेज स्रोत निर्देशिका के अंदर अपने डेटा और डॉक्स को असुविधाजनक रूप से गड़बड़ करने के लिए पाता है? (जैसे कि मेरे स्रोत को पकड़ना मेरे दस्तावेज़ से दर्जनों अवांछित हिट देता है। मैं कभी भी इसका उपयोग करने के लिए '--exclude-dir' params जोड़ सकता हूं, जो कभी भी इसका उपयोग करता है, जो एक परियोजना से दूसरे में भिन्न होगा, लेकिन ऐसा लगता है कि विकी है) यह संभव है कि मेरे पैकेज के अंदर एक 'src' सबडिर शामिल हो जो आयातों को तोड़े बिना मेरे पैकेज के अंदर है, आदि
जोनाथन हार्टले

मैं आमतौर पर केवल डेटा फ़ाइलों को रखता हूं जो पैकेज के तहत पैकेज की आवश्यकता होती है। मैं डॉक्स स्थापित करूंगा data_files। इसके अलावा, आप गैर-पायथन फ़ाइलों को अनदेखा करने के लिए grep के लिए शेल उपनाम के साथ आ सकते हैं, कुछ ऐसा grep_py
नमूनाब

अरे नमूना। अपडेट के लिए धन्यवाद। यह सिर्फ grep नहीं है, यह सब कुछ है , टेक्स्ट एडिटर सर्च-इन-फाइल्स से लेकर ctags तक जागता है। मैं आपके सुझाव को डेटा_फाइल्स में रखने के लिए अपने प्रोजेक्ट को पुनः प्राप्त करने का प्रयास करने जा रहा हूं, जैसा कि आप सुझाव देते हैं, देखें कि यह कैसे काम करता है। जल्दी वापिस आना... :-)
जोनाथन हार्टले

... यह ठीक है बाहर काम करने लगता है। मुझे सही रास्ते पर स्थापित करने के लिए धन्यवाद। +50 प्रतिष्ठा अंक स्वादिष्ट हैं?
जोनाथन हार्टले

धन्यवाद! यह सुनकर बहुत खुशी हुई, यह काम कर गया और आप प्रगति कर रहे हैं!
नमूनाब

13

मुझे लगता है कि मुझे एक अच्छा समझौता मिला, जो आपको निम्नलिखित संरचना को बदलने की अनुमति देगा:

/ #root
|- data/
|  |- resource1
|  |- [...]
|- src/
|  |- mypackage/
|  |  |- __init__.py
|  |  |- [...]
|- setup.py

आपको नमूना उत्तर में बताई गई समस्याओं से बचने के लिए पैकेज_डेटा के रूप में डेटा स्थापित करना चाहिए, लेकिन फ़ाइल संरचना को बदलने के लिए, जिसे आपको अपने सेटअप में जोड़ना चाहिए:

try:
    os.symlink('../../data', 'src/mypackage/data')
    setup(
        ...
        package_data = {'mypackage': ['data/*']}
        ...
    )
finally:
    os.unlink('src/mypackage/data')

इस तरह हम "बस समय में" उपयुक्त संरचना बनाते हैं, और हमारे स्रोत वृक्ष को व्यवस्थित करते हैं।

अपने कोड के भीतर ऐसी डेटा फ़ाइलों तक पहुँचने के लिए, आप 'बस' का उपयोग करते हैं:

data = resource_filename(Requirement.parse("main_package"), 'mypackage/data')

मुझे अभी भी कोड में 'mypackage' निर्दिष्ट करना पसंद नहीं है, क्योंकि डेटा में इस मॉड्यूल के साथ आवश्यक रूप से कुछ भी नहीं हो सकता है, लेकिन मुझे लगता है कि यह एक अच्छा समझौता है।


-4

मुझे लगता है कि आप मूल रूप से कुछ भी एक तर्क के रूप में दे सकते हैं * data_files * को सेटअप () के लिए


हम्म ... मैं देख सकता हूं कि यह डिस्टुटिल्स के डॉक्यूमेंटेशन में है, हालांकि इसे सेटपूल के डॉक्यूमेंटेशन में नहीं देखा जा सकता। वैसे भी, मैं इसे अंततः कैसे एक्सेस कर पाऊंगा?
प्रेत ०३

मुझे लगता है कि data_files का उपयोग केवल उन डेटा के लिए किया जाना चाहिए जो कई पैकेजों के बीच साझा किए जाते हैं। उदाहरण के लिए, यदि आप PyPI से इंस्टॉल करते हैं, तो data_files में सूचीबद्ध फाइलें सीधे आपके मुख्य Python install dir के अंतर्गत निर्देशिकाओं में इंस्टॉल की जाती हैं। (अर्थात, पायथन 27 / लीब / साइट-पैकेज / मायपेकेज में नहीं, लेकिन 'पायथन 27 / लीब' के समानांतर)
जोनाथन हार्टले
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.