Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- Making plugins on Python! by: Virtuos86 -------------
- I present to you an interesting article about Python. Article is not mine
- (though
- something where I worked on it, I hope not at the expense of content).
- In the attached file text article in html and txt, as well as some scripts to
- Examples. Making plugins in Python
- introduction Many programs support the so-called plug-ins (addition, expansion and
- etc.), with which you can extend the functionality of the program. In
- Python
- make programs that support plug-ins are particularly easy and pleasant
- because
- high-grade classes can act as a plug. Let's see what you need to do to your program also supports plug-ins. At the same time as it shall see
- easily.
- the first example. Main functions
- First, let's agree on the structure of the test cases. the main module
- the program will be called main.py, and plug-ins will be in the plugins
- folder, located next to the file (that is, if main.py is to
- example, in the folder C: resource, and the plugins folder must be in the
- same place)..
- To Python plugins accepted for the package, it should be a file named
- __init__.py (it will be empty in this case). First, imagine that we do not need to dynamically at runtime
- recognize the plugin name and we know it in the programming phase.
- Let plugin
- my_plugin.py has a name and is located in the plugins folder. And even
- within a file
- my_plugin.py pluginClass is a class that contains all the functionality plugin. Here is the code: class pluginClass (object): .... def __init __ (self): ........ pass def run (self): .... print u "Hello, Plug- in!"
- Ultimately, we need a run-time access to this class to instantiate and
- execute the run method. For simplicity, for the first time we agree that
- this module has no other classes except pluginClass. How would we do if
- all the names (and module, and class) would have been available at the
- time of programming? that's likely because: import plugins.my_plugin cls = plugins.my_plugin.pluginClass () cls.run ()
- And the result would have got the message "Hello, Plug-in!". Now back to
- our problem. We need to do the same, but the name of the module and
- class my_plugin pluginClass name is stored in the corresponding string
- variables. Import plug-in module. The analog built-in import directive is __import__ function, it allows you
- to import the modules whose names are in the stage of writing the
- program are unknown. In function __import__ five parameters, but only
- the first is mandatory. Optional parameters in this article we will not use,
- so keep silent about them. So, the only required parameter - this is the
- package name or a module that we want to import. If the import is successful, the function returns an instance of the class that stores all
- imported items.
- Let's start with the module import. The import directive will not help us.
- But we can
- use function __import__. An analogue of the first line of the recorded
- above an example would be the following code: package_obj = __import __ ( "plugins.my_plugin" )
- Thereafter package_obj variable will be an instance of the loaded module
- class
- (Package) plugins. To see this run: print package_obj
- (: Online print command is optional, if you call a variable
- interpreter "Default" returns the contents of the object, to which
- reference is placed in this variable through the assignment operator "=")
- At the same time we get something like (the way, of course, may be
- different): This post has little informative, so is applicable to variable package_obj
- the dir built-in function, which returns available package_obj attributes.
- Now, execute the following code: print dir (package_obj)
- As a result, the screen will indicate the following list: [ '__builtins__', '__doc__' , '__file__', '__name__', '__path__', 'my_plugin']
- Pay attention to the last item in the list - this is our plugin. So,
- package we downloaded, but how do we get to our module plugin? For
- this
- first use the built-in function getattr, which can be obtained from a
- module or package (in this case package_obj) attribute instance (and this case my_plugin). This function takes two parameters: the instance of the
- object, respectively, an attribute which is necessary to obtain and a string
- variable that contains the name of the attribute. Using the getattr
- function in the package, if successful, we will get a copy of the loaded
- module. Run the following code: module_obj = getattr (package_obj, "my_plugin ") print module_obj
- If all goes well, we will see on the screen something like this result:
- But most likely the program does not have to download a plug-in, but
- several. how
- In this case, the function will behave __import__? Consider an example in
- which downloaded two plugins (they should all be in the plugins folder, the
- easiest way
- my_plugin.py make a copy, and rename both files.). modulename1 = "my_plugin_1" modulename2 = "my_plugin_2" classname = "pluginClass1" package_obj = __import __ ( "plugins. " modulename1) package_obj = __import __ ( "plugins. " modulename2) print dir (package_obj)
- As a result, on the screen you will see the following result: [ '__builtins__', '__doc__' , '__file__', '__name__', '__path__', 'my_plugin_1', 'my_plugin_2']
- In this example, we import every time the result is assigned to the same
- variable. But as a result of the import operation after each added to it
- new imported module.
- We get access to the class
- So, my_plugin module we loaded (that is now in the plugins folder must be again
- be only one file - my_plugin.py). It remains to get to class,
- contained inside. For this we use the familiar function dir
- and make sure that is really stored in our class: print dir (module_obj)
- As a result of this code we get: [ '__builtins__', '__doc__' , '__file__', '__name__', 'pluginClass']
- As you can see, pluginClass class actually contained within module_obj.
- Again
- use getattr function: obj = getattr (module_obj, "pluginClass ") In principle, after that we can make an instance of pluginClass, but
- to start making a small test of what we got. We show that
- the resulting object really is a class, the class derived from the object. To
- do this, use the built-in issubclass. How to use it is clear from the
- following code: if issubclass (obj, object): a = obj () a.run () else: print u "Not class"
- If done correctly, the result is we will see a message "Hello,
- Plug-in! "
- And all together
- Now, for clarity, bringing together all the code that we wrote earlier. AT
- comments after the print statements given that they will bring to the screen.
- modulename = "my_plugin" classname = "pluginClass" package_obj = __import __ ( "plugins. " modulename) print package_obj # print dir (package_obj) # [ '__builtins__', '__doc__ ', '__file__', '__name__', '__path__', 'My_plugin'] module_obj = getattr (package_obj, modulename) print module_obj # print dir (module_obj) # [ '__builtins__', '__doc__ ', '__file__', '__name__', 'PluginClass'] obj = getattr (module_obj, classname) if issubclass (obj, object): print obj # a = obj () print a # a.run () else: print u "Not class"
- The second example, close to reality
- In this example, we will not know in advance the names of any modules,
- plug-ins, no class names contained within. And as we require that all
- plugins have been derived from the base class baseplugin. The plugins
- folder except the file __init__.py (remind, empty) are still three modules. One of them is named
- base.py contains a base class: class baseplugin (object): .... def run (self): ........ pass
- In the second my_plugin_1.py module contains a single class: import base class pluginClass1 (base.baseplugin): .... def __init __ (self): ........ pass def run (self): .... print u "Hello, first plug -in!" A third my_plugin_2.py two classes: import base class pluginClass2 (base.baseplugin): .... def __init __ (self): ........ pass def run (self): .... print u "Hello, second plug -in!" class pluginClass3 (base.baseplugin): .... def __init __ (self): ........ pass def run (self): .... print u "Hello, third plug -in!"
- Below is the code that gets the names of all the files in the plugins folder.
- Then import modules found (except base.py and __init__.py files). After
- that, through all the attributes within each of the imported module
- instantiates found in classes derived from base.baseplugin and executes
- the run method. import os plugin_dir = "plugins" import plugins.base
- # Here we add the names of loaded modules modules = []
- # Loop through the files in the plugins folder for fname in os.listdir (plugin_dir):
- # We are only interested in files with the extension .py if fname.endswith ( "py.") :
- # Gather the .py extension in the file name module_name = fname [: -3]
- # Skip files and base.py __init__.py if module_name = "base" and module_name = "__init__"!!: .... print u "Load module" module_name
- # Load the module and add it to the list of loaded modules package_obj = __import __ (plugin_dir ". " module_name) modules.append (module_name) print u "dir (package_obj) = " str (dir (package_obj)) print else: .... print u "Skip" fname
- # Loop through the loaded modules for modulename in modules: module_obj = getattr (package_obj, modulename) print modulename print dir (module_obj)
- # Loop through all that is inside the module for elem in dir (module_obj): .... obj = getattr (module_obj, elem )
- # Create an instance and execute the run function a = obj () a.run () print
- During the execution of the script displays additional information on the
- progress of work. AT
- resulting in the following message screen will be displayed: Skip base.py Load module my_plugin_1 dir (package_obj) = [ '__builtins__ ', '__doc__', '__file__', '__name__', '__path__', 'base', 'my_plugin_1'] Load module my_plugin_2 dir (package_obj) = [ '__builtins__ ', '__doc__', '__file__', '__name__', '__path__', 'base', 'my_plugin_1', 'my_plugin_2'] Skip __init__.py my_plugin_1 [ '__builtins__', '__doc__' , '__file__', '__name__', 'base', 'pluginClass1'] Hello, first plug-in! my_plugin_2 [ '__builtins__', '__doc__' , '__file__', '__name__', 'base', 'pluginClass2', 'pluginClass3'] Hello, second plug-in! Hello, third plug-in! Plugins and py2sis (edited)
- Make sis
- Now we learn how to work with plug-ins, and if the program
- It is distributed in the form of application.
- First, consider a simple example consisting of a main script and a plugin
- main.py plugin.py, located in the plugins folder; main.py and plugins folder (do not forget, in addition to plugin.py it should also be an empty
- __init__.py file) put in the resource folder on drive C.
- The main script (main.py): import appuifw modulename = "plugin" classname = "pluginClass" package_obj = __import __ ( "plugins. " modulename) print dir (package_obj) module_obj = getattr (package_obj, modulename) print dir (module_obj) obj = getattr (module_obj, classname) def import_plugin (): if issubclass (obj, object): .... a = obj () .... a.run () else: .... appuifw.note (u "Not class" , "error") def exit (): .... if appuifw.query (u "You want exit?", "query") == 1: .... appuifw.app.set_exit () appuifw.app.menu = [(u "Import plugin ", import_plugin), (u "Exit", exit)]
- And the source plug-in (plugin.py): class pluginClass (object): .... def __init __ (self): ........ pass def run (self): .... from appuifw import note .... note (u "Hello, Plugin !", "conf")
- If you run main.py file, the console will see the following: [ '__builtins__', '__doc__' , '__file__', '__name__', '__path__', 'plugin'] [ '__builtins__', '__doc__' , '__file__', '__name__', 'pluginClass'] Hello, Plugin!
- In order to make the sis-package, we use a great program
- SmartSIS v.2.2 by smart4n:
- Immediately I say, that I myself began to study it only recently (during
- Editing of this article), so it is to admit that some of the produced
- manipulations can be simplified by me. Also, I have no information on how to look and work the previous and subsequent versions.
- Now, run the program. Those who are familiar with it, can safely skip this
- paragraph. First of all, you need to set up a program of favorite (th):
- 1.) Go to the "Options": if the English menu, look for the item Settings ->
- "Language" -> "Russian" -> "Options" -> "save" -> "Back" and restart
- SmartSIS, the need for which we kindly and notifies the program. 2.) Run SmartSIS, -> "Options" -> "Settings" and start to configure:
- Workplace - C: or E: - here everything is just where you have more free
- space, the disk and specify. Alert - select how the notification of the
- successful completion of the operation - is determined solely by your
- culinary, musical, or even ask
- forgiveness, sexual preferences, in a word, at the user's discretion. "Kill" headband - for some reason it is recommended to put the "Yes",
- otherwise, they say, the program
- hang up - I prefer to take this advice into action.
- Packing Mode - determines the behavior of the program, for details, see
- "Help" ->
- "Help" (in which, incidentally, is all that I'm explaining) - here I guided by "Step by step wizard."
- Language - interface language selection - with this item, we are already
- familiar.
- Avtopodpis - yes, SmartSIS knows more and sign the newly created
- sis-bags, of course, if you have your certificate and key - If you select
- "Yes", then the remaining two paragraphs specify the full path to the certificate and key: for example, E: certmycert.cer and E: keymykey.key.
- However, I failed to establish devcert-signature SmartSIS, and I take
- MobileSigner by Leftup.
- Configuring SmartSIS, run X-plore, main.py put to the root of drive C (for
- simplicity). You also need to create a project folder on disk E in it to create
- the folder C, which, in turn, create a resource directory, and it finally put our folder plugins. So
- the way it will look like this:
- E: projectCresourceplugins.py.
- Now we go to smartSIS folder on the drive that you have defined as a
- worker. It create a text file py2sis.pkg, containing 13 lines:
- C: main.py_plyus_E: project main 1.0.0
- 0x7f7e8f69
- C
- Vendor
- default
- nocaps noautostart
- None
- RU
- noautorun
- nohidden
- Explanations (SmartSIS for help): 1) the full path to the script additional files (no spaces between the
- filenames and the sign _plyus_);
- 2) the name of the program, which you will see when you install the
- program in the smartphone's menu;
- 3.) version of the program: major.minor.build - required number of 3 (can
- deliver even 12345.85746353.04049.98858) and point (you can use a comma) between
- them;
- 4.) UID sis, written in hexadecimal;
- 5.) The name of the drive, which will be installed the necessary files for
- the script;
- 6) the name of the supplier, that is to say the author. Be sure to replace with your :-);
- 7) the full path to the icon in SVG or MIF format, default points to the
- Python standard icon;
- 8.) caps - for devcert applications, nocaps - for selfcert applications;
- 9) our sis-package will not have a startup function at startup;
- 10.) If you want to be displayed when you install some text (For example, the copyright of the author), then specify the full path to
- the text file
- (Win 1251 encodings, Unicode, utf-8) of no more than 1 Kbytes (None
- It means that the default text is absent);
- 11.) language code which sis-package will be packed;
- 12) the program will not start automatically after installation sis-package; 13) the program will not be hidden in the menu.
- For more information, read the FAQ in SmartSIS.
- Creating py2sis.pkg, back in SmartSIS.
- Select "Options" -> "Tools"
- -> "Py2sis". If you do not make any mistakes, py2sis starts and displays
- the information extracted from py2sis.pkg. Check it if everything is correct (pay special attention to whether the plugins and its contents included in
- the list of the folder), then "Options" -> "Compress". After the package
- you will find the full path to the sis-packed package.
- Go back to X-plore and folder:! SmartSISpacked find our sis-package that
- can be installed immediately, if you have entrusted SmartSIS signature,
- otherwise the sign themselves. Next, go to the smartphone's menu, main run our program -> "Options" -> "Import plugin" and make sure that it is
- not in vain were our efforts. Naturally main.py plugin.py and can be
- changed, with the case if the changes will have to repeat the main
- package, the plugin.py change is very simple: go to the folder:!
- Resourceplugins, plugin.py open, edit (for example, instead of writing
- "Hello, plugin! "-"! Hello, User ") and, voila, we have a new plugin with new functionality (:-) what can be verified by repeating the" Import plugin
- "!
- Thus, we are done, roughly speaking, a kind of wrapper that without
- almost any functionality, however due to the plugin can import
- capabilities to expand its functionality, and to do it, you see, is quite
- convenient. Plug-ins and additional moduli.Davayte Now make a full application of
- the example discussed in the
- the "second example, close to reality", but with a slight complication.
- Suppose that one of the plugins import other Python module, which is
- not
- It imports the main program. Suppose, for example, one of the plugins you will need a library Xoltar toolkit (author Bryn Keller) (I recently
- lecturing
- in the section Documentation / Article 3 of the articles on functional
- programming
- Python (author David Mertz), who are interested - you can search), but
- specifically it module functional. In this case, the code would look like this: import base import functional from appuifw import note class functionalpluginClass (base.baseplugin): def __init __ (self): .... pass def run (self): .... note (u "Hello, FP !", "conf") conclusion So, we have learned to do so that our program is able to dynamically load
- modules (plug-ins), and also made a full application. That's all that I
- wanted to tell :-)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement