pony icon indicating copy to clipboard operation
pony copied to clipboard

Pony and nuitka or pyinstaller

Open martinwk opened this issue 8 years ago • 7 comments

I am trying to make a standalone version of my python 2.7.12 program using the compiler nuitka and I also tried it with the freezer pyinstaller. But they fail on line 200 in pony\utils\utils.py which says:

def import_module(name):
    "import_module('a.b.c') -> <module a.b.c>"
    mod = sys.modules.get(name)
    if mod is not None: return mod
    mod = __import__(name)            # <------------- line 200
    components = name.split('.')
    for comp in components[1:]: mod = getattr(mod, comp)
    return mod

If I understand correctly, they cannot handle these import statements very well. I think it would be nice if pony is compatible with these tools which requires probably a different implementation of this import_module function. Any chance this will become available or otherwise, maybe some workarounds?

martinwk avatar Jan 26 '17 10:01 martinwk

Hm, why not importlib.import_module?

andreymal avatar Jan 26 '17 12:01 andreymal

I do not understand what you mean; do I need to replace import_module of pony with this built-in function?

martinwk avatar Jan 26 '17 13:01 martinwk

Apparently, the method import_module is only use in the method _bind in pony/orm/core.py. What I did as a quick fix was to hardcode the import command of the type of database I use, that is sqlite. Of course, this will break as soon as I use another db but works for now. Any change this will

    def _bind(self, *args, **kwargs):
        # argument 'self' cannot be named 'database', because 'database' can be in kwargs
        if self.provider is not None:
            throw(TypeError, 'Database object was already bound to %s provider' % self.provider.dialect)
        if not args:
            throw(TypeError, 'Database provider should be specified as a first positional argument')
        provider, args = args[0], args[1:]
        if isinstance(provider, type) and issubclass(provider, DBAPIProvider):
            provider_cls = provider
        else:
            if not isinstance(provider, basestring): throw(TypeError)
            if provider == 'pygresql': throw(TypeError,
                'Pony no longer supports PyGreSQL module. Please use psycopg2 instead.')
#            provider_module = import_module('pony.orm.dbproviders.' + provider)
#            provider_cls = provider_module.provider_cls
            from pony.orm.dbproviders.sqlite import SQLiteProvider as provider_cls  # <------ replaced the two commented lines above this line, with this line
        self.provider = provider = provider_cls(*args, **kwargs)

This works for pyinstaller, not sure if it works for nuitka as I still have some issues there; those issues may be unrelated to pony though.

martinwk avatar Jan 27 '17 08:01 martinwk

Ok, could not resist to try your suggestion (at least what I understood of @andreymal 's suggestion).

In pony/orm/core.py, when I imported import_module as built-in function instead of the pony\utils\utils.py version, pyinstaller also works.

In pony/orm/core.py, I removed the import of import_module from pony.utils leading to line 29-30:

from pony.utils import localbase, decorator, cut_traceback, throw, reraise, truncate_repr, get_lambda_args, \
     deprecated, parse_expr, is_ident, tostring, strjoin, concat #, <---import_module, is removed here

and added the following line below it:

from importlib import import_module

I think this would be a small change in the source and would suggest to use this for the next release.

martinwk avatar Jan 27 '17 08:01 martinwk

I seem to be having a similar issue packaging my own program with PyInstaller. I was able to get around it by manually importing pony.orm.dbproviders.sqlite, as my program uses SQLite. Are there any plans to address this issue? Perhaps a way of specifying a database provider that requires the provider to imported?

Edit: One can also include pony.orm.dbproviders.sqlite (or any other database provider) as a PyInstaller hidden import to fix this.

PotatoCurry avatar Jan 26 '20 20:01 PotatoCurry

I have the same probleme. I just manually import it: https://github.com/jgirardet/mydevoirs/blob/master/mydevoirs/database/models.py

jgirardet avatar Jan 27 '20 07:01 jgirardet

@jgirardet Thank you! It's not a fix, but you saved my day.

JackLilhammers avatar Sep 16 '20 09:09 JackLilhammers