Frage

I am writing an application in python which will be exported to an executable with py2exe. I am trying to write a plugin system which will work when the application is an exe.

My original code looked like

import os
Plugins=os.listdir('plugins')
for P in Plugins:
    PItems=os.path.splitext(P)
    PName=PItems[0]
    if PItems[len(PItems)-1]=='.py':
        Mod=__import__('plugins.'+PName,fromlist=['*'])
        Mod.init()

But when exported to exe it can not find the module 'plugins.(pluginName)' when it tries to import.

The plugins should also be able to do import my_application to access the applications api.

mcEdit (written in python) and Sublime Text (not sure) can do this but despite trawling the source code I cannot find how.

How can I write something that will work when exported to an exe?

Edit: To clarify

  • Plugins should be loaded automatically when the application loads. They are stored in the plugins/ directory
  • Plugins should be able to interact with the application with import myapplicationthen running an api call such as myapplication.getFoo() or myapplication.setBar(Bar)
  • These plugins could be run once or on an event such as mouse click or move or even every time the screen is drawn. I'd like them to keep their state (variable values, objects etc...) whilst the application is running.
War es hilfreich?

Lösung

Ok. I think I have an answer.

The file structure looks like:

api/
  - __init__.py
  - etc...
plugins/
  - plugin.py
  - etc...
- MainScript.py
- PyExeCreator.py

The MainScript.py looks like:

import os,sys, api

RootDir=os.getcwd() 
#Add this directory to export
if RootDir not in sys.path:
    sys.path.append(RootDir)

#Plugin stuff
def LoadPlugins():
    PluginsDir=os.path.join(RootDir,'plugins')
    Plugins=os.listdir(PluginsDir)

    Modules=[]
    for P in Plugins:
        PItems=os.path.splitext(P)
        PName=PItems[0]
        if PName!='__init__' and PItems[len(PItems)-1]=='.py':
            print "Loading plugins."+PName
            Mod=__import__("plugins."+PName,fromlist=['*'])
            Modules.append(Mod)
    return Modules
def RunPlugins(Modules):
    for Plugin in Modules:
        Plugin.Run()

Plugins=LoadPlugins()

#Just checking plugins can modify variables.
api.Run()
RunPlugins(Plugins)
api.Run()

The api/__init__.py looks something like:

MOTD="HI"
def Run():
    global MOTD
    print "API MOTD: "+MOTD

Probably would be a more exciting an API. plugins/plugin.py

import api
def Run():
    api.MOTD="HELLO WORLD!"
    print "This is a plugin running!"

And importantly the compiler PyExeCreator.py

from distutils.core import setup
import py2exe

setup(
    name='Tester',
    console=['Loader.py'],
    packages=['api']
)

The key bits I was missing was including the API in packages for distutils and setting the search directory for the current directory (sys.path.append(os.getcwd()))

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top