2009-09-08 37 views
26

Tôi có một dự án Python trong đó tôi đang sử dụng nhiều tệp không phải mã. Hiện tại đây là tất cả hình ảnh, nhưng tôi có thể sử dụng các loại tệp khác trong tương lai. Điều gì sẽ là một chương trình tốt để lưu trữ và tham chiếu các tệp này?Quản lý tài nguyên trong dự án Python

Tôi chỉ xem xét việc tạo một thư mục "tài nguyên" trong thư mục chính, nhưng có một vấn đề; Một số hình ảnh được sử dụng từ bên trong các gói phụ của dự án của tôi. Lưu trữ những hình ảnh theo cách đó sẽ dẫn đến khớp nối, đó là một bất lợi.

Ngoài ra, tôi cần một cách để truy cập những tệp này độc lập với thư mục hiện tại của tôi.

Trả lời

34

Bạn có thể muốn sử dụng thư viện pkg_resources đi kèm với setuptools.

Ví dụ, tôi đã thực hiện lên một cách nhanh chóng ít gói "proj" để minh họa cho chương trình tổ chức tài nguyên Tôi muốn sử dụng:

proj/setup.py 
proj/proj/__init__.py 
proj/proj/code.py 
proj/proj/resources/__init__.py 
proj/proj/resources/images/__init__.py 
proj/proj/resources/images/pic1.png 
proj/proj/resources/images/pic2.png 

Chú ý làm thế nào tôi giữ tất cả các nguồn lực trong một gói con riêng biệt.

"code.py" cho thấy cách pkg_resources được sử dụng để tham khảo các đối tượng tài nguyên:

from pkg_resources import resource_string, resource_listdir 

# Itemize data files under proj/resources/images: 
print resource_listdir('proj.resources.images', '') 
# Get the data file bytes: 
print resource_string('proj.resources.images', 'pic2.png').encode('base64') 

Nếu bạn chạy nó, bạn nhận được:

['__init__.py', '__init__.pyc', 'pic1.png', 'pic2.png'] 
iVBORw0KGgoAAAANSUhE ... 

Nếu bạn cần phải đối xử với một nguồn tài nguyên như một fileobject, sử dụng resource_stream().

Mã truy cập tài nguyên có thể ở bất kỳ đâu trong cấu trúc gói con của dự án, chỉ cần tham khảo gói phụ chứa hình ảnh theo tên đầy đủ: proj.resources.images, trong trường hợp này.

Dưới đây là "setup.py":

#!/usr/bin/env python 

from setuptools import setup, find_packages 

setup(name='proj', 
     packages=find_packages(), 
     package_data={'': ['*.png']}) 

Nên biết trước: Để kiểm tra điều "cục bộ", có nghĩa là w/o cài đặt gói đầu tiên, bạn sẽ phải gọi các kịch bản thử nghiệm của bạn từ thư mục đó có setup.py . Nếu bạn đang ở trong cùng một thư mục với tên code.py, Python sẽ không biết về gói proj. Vì vậy, những thứ như proj.resources sẽ không giải quyết được.

+1

Vâng, những bất lợi ở đây là quá nhiều. Không phải là một cách đơn giản lành mạnh để đóng gói tài nguyên với các dự án Python? –

+0

Tôi biết chỉ có 2 cách được hỗ trợ rộng rãi (chúng không đơn giản): 1) 'distutils'-way (tiêu chuẩn): tài liệu truy cập tài nguyên tập tin như một bài tập cho người đọc (có thể vì họ nghĩ rằng thao tác đường dẫn liên quan đến '__file__' là tất cả nhu cầu). 2) 'cách cài đặt' (thay thế 'dấu ngắt '), được mô tả ở trên. –

4

Bạn luôn có thể có thư mục "tài nguyên" riêng biệt trong mỗi gói con cần có và sử dụng các hàm os.path để nhận các giá trị này từ các giá trị __file__ của các gói phụ của bạn. Để minh họa cho những gì tôi muốn nói, tôi đã tạo ra __init__.py tập tin sau đây trong ba địa điểm:

 
c:\temp\topp  (top-level package) 
c:\temp\topp\sub1 (subpackage 1) 
c:\temp\topp\sub2 (subpackage 2) 

Dưới đây là file __init__.py:

import os.path 
resource_path = os.path.join(os.path.split(__file__)[0], "resources") 
print resource_path 

Trong c: \ temp \ nơi làm việc, tôi có thể tạo một ứng dụng, topapp. py, như sau:

import topp 
import topp.sub1 
import topp.sub2 

Điều này giải thích ứng dụng bằng gói topp và gói phụ. Sau đó, tôi chạy nó:

 
C:\temp\work>topapp 
Traceback (most recent call last): 
    File "C:\temp\work\topapp.py", line 1, in 
    import topp 
ImportError: No module named topp 

Đúng như mong đợi. Chúng tôi thiết lập các PYTHONPATH để mô phỏng có gói của chúng tôi trên con đường:

 
C:\temp\work>set PYTHONPATH=c:\temp 

C:\temp\work>topapp 
c:\temp\topp\resources 
c:\temp\topp\sub1\resources 
c:\temp\topp\sub2\resources 

Như bạn có thể thấy, các đường dẫn tài nguyên được giải quyết một cách chính xác đến vị trí của thực tế (sub) gói trên con đường.

Cập nhật:Here tài liệu py2exe có liên quan.

+0

Nhưng còn khi nào bạn muốn py2exe toàn bộ? –

+0

Tôi không nói về cách đóng gói tài nguyên bằng mã. Tôi đã nói về thực tế là '__file__' sẽ không hoạt động. –

1

@ pycon2009, đã có bản trình bày về các dấu rãnh và trình cài đặt. Bạn có thể tìm thấy tất cả các video ở đây

Eggs and Buildout Deployment in Python - Part 1

Eggs and Buildout Deployment in Python - Part 2

Eggs and Buildout Deployment in Python - Part 3

Trong các video này, họ mô tả làm thế nào để bao gồm các tài nguyên tĩnh trong gói của bạn. Tôi tin rằng nó trong phần 2.

Với công cụ thiết lập, bạn có thể xác định phụ thuộc, điều này sẽ cho phép bạn có 2 gói sử dụng tài nguyên từ gói thứ 3.

Công cụ thiết lập cũng cung cấp cho bạn cách truy cập thông thường các tài nguyên này và cho phép bạn sử dụng các đường dẫn tương đối bên trong gói của mình, giúp loại bỏ sự cần thiết phải lo lắng về nơi gói của bạn được cài đặt.

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