2012-06-07 40 views
25

Cách thích hợp để truy cập tài nguyên trong các chương trình python là gì.Cách truy cập các tệp tài nguyên trong python

Về cơ bản trong nhiều module python của tôi, tôi kết thúc viết code như thế:

DIRNAME = os.path.split(__file__)[0] 

    (...) 

    template_file = os.path.join(DIRNAME, "template.foo") 

Đó là OK nhưng:

  • Nó sẽ phá vỡ nếu tôi sẽ bắt đầu sử dụng các gói python zip
  • Đó là mã bản mẫu

Trong Java, tôi có một chức năng thực hiện chính xác như cũ --- nhưng làm việc cả khi mã nằm trong bó thư mục và khi mã được đóng gói trong tệp .jar.

Có chức năng như vậy trong Python hay không có bất kỳ mẫu nào khác mà tôi có thể sử dụng.

Trả lời

15

Bạn sẽ muốn xem bằng cách sử dụng get_data trong stdlib hoặc pkg_resources từ setuptools/distribution. Mà một trong những bạn sử dụng có thể phụ thuộc vào việc bạn đã sử dụng phân phối để đóng gói mã của bạn như là một quả trứng.

+0

OK đây là một câu trả lời pythonic. get_data trông thú vị, nhưng pkg_resources là cách để đe dọa, nhưng tôi chắc chắn sẽ xem xét nó khi tôi bắt đầu sử dụng các distutils để gói dự án của tôi. –

+0

Tôi đang tìm giải pháp tương tự. 'get_data' là tuyệt vời nhưng tôi cần lấy đối tượng giống như tệp cho tệp này, chứ không phải nội dung của tệp trực tiếp. Có cách nào tao nhã không? – zegkljan

+1

@zegkljan Cách pythonic nhất là quấn nó với BytesIO (StringIO trong Py2): 'file_like = BytesIO (get_data (__ package__, 'filename.dat'))' – cincodenada

-1

Tôi đoán zipimport mô-đun python tiêu chuẩn có thể là một câu trả lời ...

EDIT: tốt, không sử dụng các mô-đun trực tiếp, nhưng sử dụng sys.path như trong ví dụ này có thể là một cách tốt:

  • tôi có một file zip test.zip với một mô-đun python test và một tập tin test.foo bên
  • để kiểm tra rằng cho python nén mô-đun test có thể được nhận thức của các test.foo , Nó có chứa mã này:

c

import os 
DIRNAME = os.path.dirname(__file__) 
if os.path.exists(os.path.join(DIRNAME, 'test.foo')): 
    print 'OK' 
else: 
    print 'KO' 

thử nghiệm trông ok:

>>> import sys 
>>> sys.path.insert(0, r'D:\DATA\FP12210\My Documents\Outils\SVN\05_impl\2_tools\test.zip') 
>>> import test 
OK 
>>> 

Vì vậy, một giải pháp có thể để lặp trong file zip của bạn để lấy tất cả các module python, và thêm chúng trong sys.path; đoạn mã này lý tưởng là mã đầu tiên được ứng dụng của bạn tải.

+3

Tôi không đồng ý --- zipimport không thể nhập bất kỳ thứ gì khác mà tệp '.py [co]?'. Vì vậy, như tôi đã nói trong câu hỏi --- mã này sẽ thất bại nếu ai đó cố gắng chạy nó từ một kho lưu trữ. –

+0

Thật vậy, nhưng 'sys.path.insert (0, '/tmp/example.zip')' đưa ra một ý tưởng hay về cách làm ... – Emmanuel

2

Đang cố gắng để hiểu làm thế nào chúng ta có thể kết hợp hai khía cạnh togather

  1. tải tài nguyên trong hệ thống tập tin bản địa
  2. đóng gói trong file nén

Đọc qua hướng dẫn nhanh chóng trên zipimport: http://www.doughellmann.com/PyMOTW/zipimport/

Tôi thấy ví dụ sau:

import sys 
sys.path.insert(0, 'zipimport_example.zip') 
import os 
import zipimport 
importer = zipimport.zipimporter('zipimport_example.zip') 
module = importer.load_module('example_package') 
print module.__file__ 
print module.__loader__.get_data('example_package/README.txt') 

Tôi nghĩ rằng đầu ra của __FILE__ là "zipimport_example.zip/example_package/__init__.pyc"

Cần phải kiểm tra cách nhìn từ bên trong.

Nhưng sau đó chúng tôi luôn có thể làm một cái gì đó như thế này:

if ".zip" in example_package.__file__: 
    ... 
    load using get_data 
else: 
    load by building the correct file path 

[Edit:] Tôi đã cố gắng để làm việc ra ví dụ một chút tốt hơn.

Nếu gói được nhập dưới dạng file nén sau đó, có hai điều xảy ra

  1. __FILE__ chứa ".zip" trong đó là con đường.
  2. __loader__ có sẵn trong không gian tên

Nếu hai điều kiện này được đáp ứng thì trong thời hạn gói bạn có thể làm:

print __loader__.get_data(os.path.join('package_name','README.txt')) 

khác các module đã được nạp bình thường và bạn có thể làm theo các cách tiếp cận thường xuyên để tải tệp.

+0

@jb .: Câu hỏi khó. Tôi vẫn cần phải làm việc này. – pyfunc

+0

bạn nên sử dụng 'os.path.join ('example_package', 'README.txt')' nếu bạn muốn nền tảng độc lập – kratenko

+0

@jb: Giải pháp này có tốt hơn cho bạn không. – pyfunc

Các vấn đề liên quan