5

Tôi đang làm việc trên một dự án có nguyên tắc hướng dẫn thiết kế chính là khả năng mở rộng.Làm cách nào để sắp xếp cấu trúc tệp của hệ thống plugin đã hoạt động của tôi?

Tôi đã triển khai hệ thống plugin bằng cách xác định metaclass đăng ký - với phương thức lớp - tên lớp của bất kỳ plugin nào được tải (mỗi loại plugin kế thừa từ một lớp cụ thể được xác định trong mã lõi). là các loại plugin khác nhau trong ứng dụng). Về cơ bản điều này có nghĩa rằng một nhà phát triển sẽ phải xác định đẳng cấp của mình như

class PieChart(ChartPluginAncestor): 
    # Duck typing: 
    # Implement compulsory methods for Plugins 
    # extending Chart functionality 

và chương trình chính sẽ biết sự hiện diện của mình bởi vì PieChart sẽ được đưa vào danh sách các plugin đã đăng ký có sẵn tại ChartPluginAncestor.plugins.

Là phương pháp gắn kết một phương thức lớp, tất cả các plugin được đăng ký khi mã lớp của chúng được tải vào bộ nhớ (vì vậy ngay cả trước khi đối tượng của lớp đó được khởi tạo).

Hệ thống hoạt động đủ ™ tốt cho tôi (mặc dù tôi luôn luôn mở để gợi ý về cách cải thiện kiến ​​trúc!) Nhưng bây giờ tôi tự hỏi điều gì sẽ là cách tốt nhất để quản lý các tập tin plugin (tức là nơi và cách các tệp chứa các plugin phải được lưu trữ).

Cho đến nay tôi đang sử dụng - cho mục đích phát triển - một gói mà tôi gọi là "plugin". Tôi đặt tất cả các tệp * .py chứa các lớp bổ trợ trong thư mục gói và tôi chỉ phát hành import plugins trong tệp main.py, để tất cả các plugin được gắn đúng cách.

EDIT: Jeff đã chỉ ra trong các ý kiến ​​rằng import plugins các lớp có trong các mô-đun khác nhau của gói sẽ không có sẵn (tôi không nhận ra điều này như tôi đã - cho mục đích gỡ lỗi - nhập từng lớp riêng biệt với from plugins.myAI import AI).

Tuy nhiên hệ thống này chỉ tốt trong khi tôi đang phát triển và thử nghiệm mã, như:

  • Plugins có thể đi kèm với unittests riêng của họ, và tôi không muốn tải những trong bộ nhớ.
  • Tất cả các plugin hiện được tải vào bộ nhớ, nhưng thực sự có một số plugin là phiên bản thay thế của cùng một tính năng, vì vậy bạn chỉ cần biết rằng bạn có thể chuyển đổi giữa hai plugin, nhưng bạn chỉ muốn tải vào bộ nhớ một trong những bạn đã chọn từ cửa sổ cấu hình.
  • Tại một thời điểm nào đó, tôi sẽ muốn có vị trí kép để cài đặt plugin: vị trí trên toàn hệ thống (ví dụ: một nơi nào đó dưới /usr/local/bin/) và một người dùng cụ thể (ví dụ: ở đâu đó theo số /home/<user>/.myprogram/).

Vì vậy, câu hỏi của tôi là thực sự - có lẽ - ba: container

  1. Plugin: lựa chọn hợp lý nhất là những gì cho mục tiêu của tôi? các tệp đơn lẻ? gói? một thư mục đơn giản của các tệp .py?)
  2. Nhận biết sự hiện diện của các trình cắm mà không nhất thiết phải tải (nhập) chúng: cách thông minh để sử dụng tính năng intropection của Python là gì?
  3. Đặt plugin ở hai vị trí khác nhau: có cách nào/cách thực hành tốt nhất (dưới gnu/linux, ít nhất) để làm điều đó không?
+1

Tôi nghĩ rằng 'các plugin nhập 'sẽ chỉ tải gói và không phải mô-đun trong gói. –

+0

Đây là gợi ý tôi đang tìm kiếm! :) – mac

Trả lời

3

Câu hỏi khó giải quyết, vì nhu cầu rất phức tạp. Dù sao thì tôi cũng sẽ thử một số gợi ý.

Về

plugin Đặt trong hai địa điểm khác nhau: là có một cách tiêu chuẩn/ thực hành tốt nhất (dưới GNU/Linux, tại nhất) để làm điều đó?

Cách tiếp cận tốt là virtualenv. Virtualenv là một mô-đun python để xây dựng cài đặt python "cô lập". Đó là cách tốt hơn để có được các dự án riêng biệt làm việc cùng nhau. Bạn nhận được một gói trang web hoàn toàn mới, nơi bạn có thể đặt các plugin của mình với các mô-đun dự án có liên quan.

Hãy thử: http://pypi.python.org/pypi/virtualenv

Plugin container: các sự lựa chọn hợp lý nhất cho mục tiêu của tôi là gì? duy nhất tệp? gói? ? Một thư mục đơn giản của file py)

Một cách tiếp cận tốt là một gói python mà có thể làm một "tự đăng ký" khi nhập khẩu: chỉ cần xác định bên trong thư mục gói một hợp init py

Một ví dụ có thể http://www.qgis.org/wiki/Writing_Python_Plugins và cũng là API mô tả ở đây http://twistedmatrix.com/documents/current/core/howto/plugin.html

Xem thêm http://pypi.python.org/pypi/giblets/0.2.1

Giblets là hệ thống plugin đơn giản dựa trên kiến ​​trúc thành phần của Trac. Tóm lại, giblets cho phép bạn khai báo giao diện và khám phá các thành phần triển khai chúng mà không cần khớp nối .

tự tôn cũng bao gồm Plugin khám phá dựa trên đường dẫn tập tin hoặc các điểm entry cùng với phương tiện linh hoạt để quản lý mà thành phần được kích hoạt hay vô hiệu hóa trong ứng dụng của bạn.

+0

Cảm ơn bạn đã trả lời và cho các liên kết khác nhau (+1). Tôi đọc về giblets trước đây, nhưng tôi không thích thiết kế của nó lắm. Duck gõ là tốt, introspection là tốt. Phải tuyên bố "implments" là ... tốt ... ít tốt! Mặt khác, nó phát hiện ra plugin theo đường dẫn, vì vậy tôi có thể xem xét mã nguồn của nó và kiểm tra xem nó thực hiện tương thích nền tảng như thế nào. Ngoài ra các tính năng danh sách trắng/danh sách đen là tốt cho tôi. Virtualenv - mặt khác - là cách vượt ra ngoài nhu cầu của tôi. Tôi hài lòng với một môi trường duy nhất, tôi chỉ muốn các đường dẫn tìm kiếm khác nhau cho những người dùng khác nhau! – mac

1

Tôi cũng có hệ thống plugin với ba loại plugin, mặc dù tôi không tuyên bố đã làm tốt. Bạn có thể xem một số chi tiết here.

Đối với plugin nội bộ, tôi có một gói (ví dụ: MethodPlugins) và trong gói này là một mô-đun cho mỗi plugin (ví dụ: MethodPlugins.IRV).Dưới đây là cách tôi tải các plug-in:

  1. tải gói (import MethodPlugins)

  2. Sử dụng pkgutil.iter_modules để tải tất cả các module đó (ví dụ, MethodPlugins.IRV)

  3. Tất cả các plugin xuống từ một lớp cơ sở chung để tôi có thể sử dụng __subclassess__ để xác định tất cả.

Tôi tin rằng điều này sẽ cho phép bạn nhận ra plugin mà không thực sự tải chúng, mặc dù tôi không làm điều đó vì tôi chỉ tải tất cả.

Đối với các plugin bên ngoài, tôi có một thư mục được chỉ định nơi người dùng có thể đặt chúng và tôi sử dụng os.listdir để nhập chúng. Người dùng được yêu cầu sử dụng lớp cơ sở phù hợp để tôi có thể tìm thấy chúng.

Tôi cũng muốn cải thiện điều này, nhưng nó cũng hoạt động tốt đủ cho tôi. :)

+0

Cảm ơn bạn đã trả lời. Lời khuyên tốt nhất (một trong đó đã cho tôi cái nhìn mới/mẩu thông tin mà tôi đang tìm kiếm, bạn đã cho tôi bình luận của bạn với câu trả lời mặc dù. Tôi đã vội vàng viết 'từ plugins.betterai nhập AI' và không Tôi nghĩ rằng sau đó tôi sẽ giữ các plugin của tôi dưới dạng gói và kiểm tra liên kết bạn đã đăng ở trên để xem cách bạn đã thực hiện hệ thống của riêng mình. Tôi sẽ báo cáo lại khi tôi đã có một giải pháp làm việc. – mac

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