2011-10-25 28 views
11

Tôi đang sử dụng Python 2.6 và PyGTK 2.22.6 từ all-in-one installer trên Windows XP, cố gắng xây dựng một tệp thực thi (thông qua py2exe) cho ứng dụng của tôi.Gộp tài nguyên GTK với py2exe

Vấn đề của tôi là khi tôi chạy ứng dụng của mình dưới dạng tập lệnh (ví dụ: không được tích hợp vào tệp .exe, cũng như tập hợp .py tệp), nó sử dụng chủ đề Windows có nguồn gốc, nhưng khi tôi chạy xây dựng exe tôi thấy chủ đề GTK mặc định.

Tôi biết rằng sự cố này có thể được khắc phục bằng cách sao chép một loạt tệp vào thư mục dist được tạo bởi py2exe, nhưng mọi thứ tôi đã đọc liên quan đến việc sao chép dữ liệu theo cách thủ công, trong khi tôi muốn đây là phần tự động của bản dựng quá trình. Hơn nữa, tất cả mọi thứ về chủ đề (bao gồm the FAQ) đã lỗi thời - PyGTK hiện giữ các tệp trong C:\Python2x\Lib\site-packages\gtk-2.0\runtime\... và chỉ sao chép các thư mục libetc không khắc phục được sự cố.

Câu hỏi của tôi là:

  1. Tôi muốn để có thể lập trình tìm dữ liệu thời gian chạy GTK trong setup.py chứ không phải là con đường mã hóa cứng. Làm thế nào để tôi làm điều này?

  2. Tài nguyên tối thiểu tôi cần bao gồm là gì?

Cập nhật: tôi có thể đã gần như đã trả lời # 2 bằng cách thử-và-lỗi. (. Tức là MS Windows) cho "kẻ yếu đuối" chủ đề để làm việc, tôi cần các tập tin từ:

runtime\lib\gtk-2.0\2.10.0\engines\libwimp.dll 
runtime\etc\gtk-2.0\gtkrc 
runtime\share\icons\* 
runtime\share\themes\MS-Windows 

... không có tiền tố runtime, nhưng mặt khác với cấu trúc thư mục giống nhau, ngồi trực tiếp trong thư mục dist được sản xuất bởi py2exe. Nhưng ở đâu, 2.10.0 đến từ, cho rằng gtk.gtk_version(2,22,0)?

Trả lời

9

Trả lời câu hỏi của riêng tôi tại đây, nhưng nếu có ai biết tốt hơn cũng có thể trả lời. Một số có vẻ khá mong manh (ví dụ: số phiên bản trong đường dẫn), vì vậy hãy nhận xét hoặc chỉnh sửa nếu bạn biết cách tốt hơn.

1. Tìm file

Thứ nhất, tôi sử dụng mã này để thực sự tìm ra gốc rễ của thời gian chạy GTK. Đây là rất cụ thể để làm thế nào bạn cài đặt thời gian chạy, tuy nhiên, và có lẽ có thể được cải thiện với một số kiểm tra cho các địa điểm chung:

#gtk file inclusion 
import gtk 
# The runtime dir is in the same directory as the module: 
GTK_RUNTIME_DIR = os.path.join(
    os.path.split(os.path.dirname(gtk.__file__))[0], "runtime") 

assert os.path.exists(GTK_RUNTIME_DIR), "Cannot find GTK runtime data" 

2. gì file để bao gồm

này phụ thuộc vào (a) kích thước mối quan tâm là bao nhiêu, và (b) bối cảnh triển khai ứng dụng của bạn. Ý tôi là, bạn đang triển khai nó cho toàn bộ thế giới nơi mọi người có thể có một thiết lập địa phương tùy ý, hay chỉ để sử dụng nội bộ doanh nghiệp mà bạn không cần chuỗi mã dịch?

Nếu bạn muốn Windows theming, bạn sẽ cần phải bao gồm:

GTK_THEME_DEFAULT = os.path.join("share", "themes", "Default") 
GTK_THEME_WINDOWS = os.path.join("share", "themes", "MS-Windows") 
GTK_GTKRC_DIR = os.path.join("etc", "gtk-2.0") 
GTK_GTKRC = "gtkrc" 
GTK_WIMP_DIR = os.path.join("lib", "gtk-2.0", "2.10.0", "engines") 
GTK_WIMP_DLL = "libwimp.dll" 

Nếu bạn muốn các biểu tượng Tango:

GTK_ICONS = os.path.join("share", "icons") 

Ngoài ra còn có dữ liệu nội địa (mà tôi bỏ qua, nhưng bạn có thể không muốn):

GTK_LOCALE_DATA = os.path.join("share", "locale") 

3. Giành nó cùng

Thứ nhất, đây là một hàm chạy cây hệ thống tập tin tại một điểm đã cho và tạo đầu ra phù hợp với tùy chọn data_files.

def generate_data_files(prefix, tree, file_filter=None): 
    """ 
    Walk the filesystem starting at "prefix" + "tree", producing a list of files 
    suitable for the data_files option to setup(). The prefix will be omitted 
    from the path given to setup(). For example, if you have 

     C:\Python26\Lib\site-packages\gtk-2.0\runtime\etc\... 

    ...and you want your "dist\" dir to contain "etc\..." as a subdirectory, 
    invoke the function as 

     generate_data_files(
      r"C:\Python26\Lib\site-packages\gtk-2.0\runtime", 
      r"etc") 

    If, instead, you want it to contain "runtime\etc\..." use: 

     generate_data_files(
      r"C:\Python26\Lib\site-packages\gtk-2.0", 
      r"runtime\etc") 

    Empty directories are omitted. 

    file_filter(root, fl) is an optional function called with a containing 
    directory and filename of each file. If it returns False, the file is 
    omitted from the results. 
    """ 
    data_files = [] 
    for root, dirs, files in os.walk(os.path.join(prefix, tree)):   
     to_dir = os.path.relpath(root, prefix) 

     if file_filter is not None: 
      file_iter = (fl for fl in files if file_filter(root, fl)) 
     else: 
      file_iter = files 

     data_files.append((to_dir, [os.path.join(root, fl) for fl in file_iter])) 

    non_empties = [(to, fro) for (to, fro) in data_files if fro] 

    return non_empties 

Vì vậy, bây giờ bạn có thể gọi setup() như vậy:

setup(
    # Other setup args here... 

    data_files = (
        # Use the function above... 
        generate_data_files(GTK_RUNTIME_DIR, GTK_THEME_DEFAULT) + 
        generate_data_files(GTK_RUNTIME_DIR, GTK_THEME_WINDOWS) + 
        generate_data_files(GTK_RUNTIME_DIR, GTK_ICONS) + 

        # ...or include single files manually 
        [ 
         (GTK_GTKRC_DIR, [ 
          os.path.join(GTK_RUNTIME_DIR, 
           GTK_GTKRC_DIR, 
           GTK_GTKRC) 
         ]), 

         (GTK_WIMP_DIR, [ 
          os.path.join(
           GTK_RUNTIME_DIR, 
           GTK_WIMP_DIR, 
           GTK_WIMP_DLL) 
         ]) 
        ] 
       ) 
)