Câu hỏi Truy cập dữ liệu Python trong thư mục con gói


Tôi đang viết một gói python với các mô-đun cần mở các tệp dữ liệu trong một ./data/ thư mục con. Ngay bây giờ tôi có các đường dẫn đến các tệp được mã hóa cứng vào các lớp và các hàm của tôi. Tôi muốn viết mã mạnh mẽ hơn có thể truy cập vào thư mục phụ bất kể nó được cài đặt ở đâu trên hệ thống của người dùng.

Tôi đã thử một loạt các phương pháp, nhưng cho đến nay tôi đã không có may mắn. Dường như hầu hết các lệnh "thư mục hiện tại" trả về thư mục của trình thông dịch python của hệ thống, chứ không phải thư mục của mô-đun.

Điều này có vẻ như nó phải là một vấn đề thường gặp. Nhưng tôi không thể hình dung ra được. Một phần của vấn đề là các tệp dữ liệu của tôi không .py tệp, vì vậy tôi không thể sử dụng chức năng nhập và các chức năng tương tự.

Bất kỳ đề xuất?

Ngay bây giờ thư mục gói của tôi trông giống như:

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

Tôi đang cố truy cập data.txt từ module*.py

Cảm ơn!


76
2018-04-22 22:17


gốc


Xem thêm: Làm thế nào để đọc một tập tin (tĩnh) từ bên trong một gói Python? - Martin Thoma


Các câu trả lời:


Bạn có thể sử dụng gạch dưới-gạch dưới-tệp-gạch dưới-gạch dưới (__file__) để có được đường dẫn đến gói, như thế này:

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



Điều này sẽ không hoạt động nếu các tệp nằm trong bản phân phối (trứng của IE). Sử dụng pkg_resources để lấy tệp dữ liệu. - Chris
Thật vậy, điều này bị hỏng. - Federico
Cũng thế, __file__ không hoạt động với py2exe, vì giá trị sẽ là đường dẫn đến tệp zip. - Pod


Cách tiêu chuẩn để làm điều này là với các gói setuptools và pkg_resources.

Bạn có thể đặt gói của mình theo thứ bậc sau và định cấu hình tệp thiết lập gói để trỏ nó vào tài nguyên dữ liệu của bạn, theo liên kết này:

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

Sau đó, bạn có thể tìm lại và sử dụng các tệp đó bằng cách sử dụng pkg_resources, theo liên kết này:

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



Tôi nghĩ rằng đây là cách ưa thích, tôi không hoàn toàn chắc chắn về lý do nhưng dự án hiển thị cảnh báo khi bạn tham khảo gói / mô-đun với __file__. - lukecampbell
Sẽ không pkg_resources tạo phụ thuộc vào thời gian chạy trên setuptools? Ví dụ, tôi phân phối lại gói Debian, vậy tại sao tôi lại phụ thuộc vào python-setuptools chỉ cho điều đó? Cho đến nay __file__ làm việc tốt cho tôi. - mlt
Tại sao điều này tốt hơn: Lớp ResourceManager cung cấp quyền truy cập thống nhất vào tài nguyên gói, cho dù các tài nguyên đó tồn tại dưới dạng tệp và thư mục hay được nén trong một tệp lưu trữ của một số loại - vrdhn
Gợi ý rực rỡ, cảm ơn. Tôi đã triển khai một tệp chuẩn mở bằng from pkg_resources import resource_filename open(resource_filename('data', 'data.txt'), 'rb') - niallsco
Làm thế nào điều này sẽ làm việc cho việc sử dụng các gói phần mềm khi nó không được cài đặt? Chỉ cần thử nghiệm tại địa phương tôi có nghĩa là - Claudiu


Để cung cấp một giải pháp làm việc ngày hôm nay. Chắc chắn sử dụng API này để không phát minh lại tất cả các bánh xe đó.

Cần có tên tệp hệ thống tệp thực sự. Trứng nén sẽ được trích xuất vào thư mục bộ nhớ cache:

from pkg_resources import resource_filename, Requirement

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

Trả về một đối tượng giống như tệp có thể đọc được cho tài nguyên được chỉ định; nó có thể là một tập tin thực tế, một StringIO, hoặc một số đối tượng tương tự. Luồng đang ở trong "chế độ nhị phân", theo nghĩa là bất kỳ byte nào trong tài nguyên sẽ được đọc dưới dạng.

from pkg_resources import resource_stream, Requirement

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

Khám phá gói và truy cập tài nguyên bằng cách sử dụng pkg_resources


12
2017-10-09 12:33





Tôi nghĩ tôi đã tìm ra câu trả lời.

Tôi tạo một mô-đun data_path.py, mà tôi nhập vào các mô-đun khác của tôi có chứa:

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

Và sau đó tôi mở tất cả các tệp của mình

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

6
2018-04-22 22:35



Điều này sẽ không hoạt động khi tài nguyên nằm trong bản phân phối lưu trữ (chẳng hạn như trứng nén). Thích một cái gì đó như thế: pkg_resources.resource_string('pkg_name', 'data/file.txt') - ankostis
@ankostis setuptools đủ thông minh để trích xuất kho lưu trữ nếu phát hiện thấy bạn đã sử dụng __file__ một vài nơi. Trong trường hợp của tôi, tôi sử dụng một thư viện mà thực sự muốn con đường và không phải dòng. Tất nhiên tôi có thể ghi các tập tin tạm thời vào đĩa nhưng bị lười, tôi chỉ sử dụng tính năng của setuptools. - letmaik


Bạn cần một tên cho toàn bộ mô-đun của bạn, bạn được đưa ra cây thư mục không liệt kê chi tiết đó, đối với tôi điều này đã làm việc:

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

Các tập tin cài đặt không rõ ràng dường như không giải quyết các tệp dựa trên tên phù hợp với các tệp dữ liệu được đóng gói, bạn cần phải bao gồm data/ tiền tố khá nhiều không có vấn đề gì. Bạn có thể dùng os.path.join('data', 'data.txt) nếu bạn cần bộ tách thư mục thay thế, Nói chung tôi không tìm thấy vấn đề tương thích với phân cách thư mục phong cách unix mã hóa cứng mặc dù.


5
2017-12-10 09:59



docs.python.org/3.6/distutils/… > Lưu ý rằng bất kỳ tên đường dẫn nào (tệp hoặc thư mục) được cung cấp trong tập lệnh thiết lập phải được viết bằng quy ước Unix, tức là tách biệt dấu gạch chéo. Các Distutils sẽ chăm sóc chuyển đổi biểu diễn nền tảng trung lập này thành bất kỳ thứ gì phù hợp trên nền tảng hiện tại của bạn trước khi thực sự sử dụng tên đường dẫn. Điều này làm cho kịch bản thiết lập của bạn di động trên các hệ điều hành, tất nhiên là một trong những mục tiêu chính của Distutils. Trong tinh thần này, tất cả các tên đường dẫn trong tài liệu này được phân tách bằng dấu gạch chéo. - changyuheng