Używam setuptools do dystrybucji mojego pakietu Pythona. Teraz muszę rozprowadzić dodatkowe pliki danych.
Z tego, co zebrałem z dokumentacji setuptools, muszę mieć moje pliki danych w katalogu pakietu. Jednak wolałbym, aby moje pliki danych znajdowały się w podkatalogu w katalogu głównym.
Czego chciałbym uniknąć:
/ #root
|- src/
| |- mypackage/
| | |- data/
| | | |- resource1
| | | |- [...]
| | |- __init__.py
| | |- [...]
|- setup.py
Co chciałbym zamiast tego mieć:
/ #root
|- data/
| |- resource1
| |- [...]
|- src/
| |- mypackage/
| | |- __init__.py
| | |- [...]
|- setup.py
Po prostu nie czuję się komfortowo mając tak wiele podkatalogów, jeśli nie jest to konieczne. Nie mogę znaleźć powodu, dla którego / mam / umieszczam pliki w katalogu pakietu. Praca z tak wieloma zagnieżdżonymi podkatalogami IMHO jest również uciążliwa. A może jest jakiś dobry powód, który uzasadniałby to ograniczenie?
python
setuptools
phant0m
źródło
źródło
__init__.py
plik, nawet jeśli ten plik jest pusty. Możesz więc oddzielić katalog danych pustym__init__.py
plikiem, aby wyglądał jak pakiet. Powinno to uniemożliwić grepowi pobranie ich z drzewa źródłowego, ale nadal będzie rozpoznawany jako pakiet przez Pythona i jego narzędzia do budowania.Odpowiedzi:
Opcja 1: Zainstaluj jako dane pakietu
Główną zaletą umieszczania plików danych w katalogu głównym pakietu Pythona jest to, że pozwala uniknąć martwienia się o to, gdzie pliki będą znajdować się w systemie użytkownika, którym może być Windows, Mac, Linux, jakaś platforma mobilna lub wewnątrz Egg. Zawsze możesz znaleźć katalog
data
względem katalogu głównego pakietu Pythona, bez względu na to, gdzie i jak jest zainstalowany.Na przykład, jeśli mam taki układ projektu:
Możesz dodać funkcję do,
__init__.py
aby zlokalizować bezwzględną ścieżkę do pliku danych: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')
Wyjścia:
Po zainstalowaniu projektu jako Egg ścieżka do
data
zmieni się, ale kod nie musi się zmieniać:/Users/pat/virtenv/foo/lib/python2.6/site-packages/foo-0.0.0-py2.6.egg/foo/data/resource1/foo.txt
Opcja 2: Zainstaluj w stałej lokalizacji
Alternatywą byłoby umieszczenie danych poza pakietem Pythona, a następnie:
data
przekazaną za pośrednictwem pliku konfiguracyjnego, argumentów wiersza poleceń lubJest to znacznie mniej pożądane, jeśli planujesz rozpowszechniać swój projekt. Jeśli naprawdę chcesz to zrobić, możesz zainstalować swój w
data
dowolnym miejscu w systemie docelowym, określając miejsce docelowe dla każdej grupy plików, przekazując listę krotek:from setuptools import setup setup( ... data_files=[ ('/var/data1', ['data/foo.txt']), ('/var/data2', ['data/bar.txt']) ] )
Zaktualizowano : Przykład funkcji powłoki rekurencyjnej do plików grep Python:
atlas% function grep_py { find . -name '*.py' -exec grep -Hn $* {} \; } atlas% grep_py ": \[" ./setup.py:9: package_data={'foo': ['data/resource1/foo.txt']}
źródło
data_files
. Możesz także wymyślić alias powłoki dla grep, aby ignorować pliki spoza Pythona, na przykładgrep_py
.Myślę, że znalazłem dobry kompromis, który pozwoli Ci zachować następującą strukturę:
/ #root |- data/ | |- resource1 | |- [...] |- src/ | |- mypackage/ | | |- __init__.py | | |- [...] |- setup.py
Powinieneś zainstalować dane jako package_data, aby uniknąć problemów opisanych w przykładowej odpowiedzi bias, ale aby zachować strukturę pliku, powinieneś dodać do swojego setup.py:
try: os.symlink('../../data', 'src/mypackage/data') setup( ... package_data = {'mypackage': ['data/*']} ... ) finally: os.unlink('src/mypackage/data')
W ten sposób tworzymy odpowiednią strukturę „just in time” i utrzymujemy uporządkowane drzewo źródłowe.
Aby uzyskać dostęp do takich plików danych w swoim kodzie, „po prostu” użyj:
data = resource_filename(Requirement.parse("main_package"), 'mypackage/data')
Nadal nie lubię określać „mypackage” w kodzie, ponieważ dane mogą nie mieć nic wspólnego z tym modułem, ale myślę, że to dobry kompromis.
źródło
Myślę, że w zasadzie możesz podać wszystko jako argument * data_files * do setup () .
źródło