Pytanie Python Access Data in Package Subdirectory


Piszę pakiet python z modułami, które muszą otwierać pliki danych w ./data/ podkatalog. Teraz mam ścieżki do plików zakodowanych na moich zajęciach i funkcjach. Chciałbym napisać bardziej niezawodny kod, który może uzyskać dostęp do podkatalogu, niezależnie od tego, gdzie jest zainstalowany w systemie użytkownika.

Próbowałem różnych metod, ale do tej pory nie miałem szczęścia. Wygląda na to, że większość poleceń "katalogu bieżącego" zwraca katalog pythonowego interpretera systemu, a nie katalog modułu.

Wygląda na to, że powinien to być zwyczajny, powszechny problem. Jednak nie mogę tego zrozumieć. Częściowo problem polega na tym, że moje pliki danych nie są .py plików, więc nie mogę używać funkcji importowania i tym podobnych.

Jakieś sugestie?

Teraz mój katalog pakietów wygląda tak:

/
__init__.py
module1.py
module2.py
data/   
   data.txt

Próbuję uzyskać dostęp data.txt od module*.py

Dzięki!


76
2018-04-22 22:17


pochodzenie


Zobacz też: Jak odczytać (statyczny) plik z wnętrza pakietu Pythona? - Martin Thoma


Odpowiedzi:


Możesz użyć podkreślenia-podkreślenia-pliku-podkreślenia-podkreślenia (__file__), aby uzyskać ścieżkę do pakietu, na przykład:

import os
this_dir, this_filename = os.path.split(__file__)
DATA_PATH = os.path.join(this_dir, "data", "data.txt")
print open(DATA_PATH).read()

23
2018-04-22 22:37



To nie zadziała, jeśli pliki są w dystrybucji (np. Jajeczko). Użyj pkg_resources, aby uzyskać dostęp do pliku danych. - Chris
Rzeczywiście jest to zepsute. - Federico
Również, __file__ nie działa z py2exe, ponieważ wartość będzie ścieżką do pliku zip. - Pod


Standardowy sposób to zrobić z pakietami setuptools i pkg_resources.

Możesz rozmieścić pakiet zgodnie z poniższą hierarchią i skonfigurować plik konfiguracyjny pakietu, aby wskazał mu zasoby danych, zgodnie z tym łączem:

http://docs.python.org/distutils/setupscript.html#installing-package-data

Następnie można ponownie znaleźć i użyć tych plików za pomocą pkg_resources, zgodnie z tym łączem:

http://peak.telecommunity.com/DevCenter/PkgResources#basic-resource-access

import pkg_resources

DATA_PATH = pkg_resources.resource_filename('<package name>', 'data/')
DB_FILE = pkg_resources.resource_filename('<package name>', 'data/sqlite.db')

109
2018-04-08 23:42



Myślę, że jest to preferowany sposób, nie jestem do końca pewny powodu, ale projekty wyświetlają ostrzeżenia, gdy odwołujesz się do pakietu / modułu z __file__. - lukecampbell
Przyzwyczajenie pkg_resources utworzyć zależność od czasu wykonywania setuptools? Na przykład, redystrybuuję pakiet Debiana, więc dlaczego miałbym na tym polegać python-setuptools tylko po to? Jak dotąd __file__ działa dobrze dla mnie. - mlt
Dlaczego jest to lepsze: klasa ResourceManager zapewnia jednolity dostęp do zasobów pakietów, niezależnie od tego, czy te zasoby istnieją jako pliki i katalogi czy są skompresowane w jakimś archiwum - vrdhn
Genialna sugestia, dzięki. Zaimplementowałem standardowy plik otwarty from pkg_resources import resource_filename open(resource_filename('data', 'data.txt'), 'rb') - niallsco
Jak to zadziała w przypadku korzystania z pakietu, gdy nie jest zainstalowany? Mam na myśli tylko testowanie na miejscu - Claudiu


Aby zapewnić rozwiązanie działające do dziś. Zdecydowanie użyj tego API, aby nie wymyślać wszystkich tych kół.

Wymagana jest prawdziwa nazwa systemu plików. Spakowane jajka zostaną wyodrębnione do katalogu pamięci podręcznej:

from pkg_resources import resource_filename, Requirement

path_to_vik_logo = resource_filename(Requirement.parse("enb.portals"), "enb/portals/reports/VIK_logo.png")

Zwraca czytelny obiekt podobny do pliku dla określonego zasobu; może to być rzeczywisty plik, StringIO lub jakiś podobny obiekt. Strumień jest w "trybie binarnym" w tym sensie, że wszystkie bajty w zasobach będą czytane tak jak są.

from pkg_resources import resource_stream, Requirement

vik_logo_as_stream = resource_stream(Requirement.parse("enb.portals"), "enb/portals/reports/VIK_logo.png")

Wykrywanie pakietów i dostęp do zasobów za pomocą pkg_resources


12
2017-10-09 12:33





Myślę, że szukałem odpowiedzi.

Tworzę moduł data_path.py, który importuję do innych moich modułów zawierających:

data_path = os.path.join(os.path.dirname(__file__),'data')

A potem otwieram wszystkie moje pliki

open(os.path.join(data_path,'filename'), <param>)

6
2018-04-22 22:35



To nie zadziała, gdy zasób znajduje się w dystrybucji archiwum (takiej jak zipowane jajko). Preferuj coś takiego: pkg_resources.resource_string('pkg_name', 'data/file.txt') - ankostis
@kostostis setuptools jest na tyle sprytny, aby wyodrębnić archiwum, jeśli wykryje, że użyłeś __file__ gdzieś. W moim przypadku używam biblioteki, która naprawdę chce ścieżek, a nie strumieni. Oczywiście mogłem tymczasowo zapisać pliki na dysku, ale będąc leniwym, używam tylko funkcji setuptools. - letmaik


Potrzebujesz nazwy dla całego modułu, dostaniesz drzewo katalogów, które nie podaje tego szczegółu, dla mnie to zadziałało:

import pkg_resources
print(    
    pkg_resources.resource_filename(__name__, 'data/data.txt')
)

Zauważalnie setuptools nie wydaje się rozwiązywać plików na podstawie dopasowania nazwy do spakowanych plików danych, więc musisz dodać data/ Prefiks prawie bez względu na wszystko. Możesz użyć os.path.join('data', 'data.txt) jeśli potrzebujesz alternatywnych separatorów katalogów, Generalnie nie znajduję problemów ze zgodnością z zakodowanymi w sztywno katalogami typu UNIX.


5
2017-12-10 09:59



docs.python.org/3.6/distutils/... > Zauważ, że wszystkie nazwy ścieżek (pliki lub katalogi) dostarczone w skrypcie instalacyjnym powinny być zapisane przy użyciu konwencji uniksowej, tj. Oddzielone ukośnikami. Distutils zajmie się przekształceniem tej neutralnej platformy w to, co jest odpowiednie na twojej obecnej platformie, zanim faktycznie użyje ścieżki. To sprawia, że ​​twój skrypt instalacyjny jest przenośny w różnych systemach operacyjnych, co oczywiście jest jednym z głównych celów Distutils. W tym duchu wszystkie nazwy ścieżek w tym dokumencie są rozdzielone przecinkami. - changyuheng