python - Import hooks for PyQt4.QtCore -
i'm attempting setup import hooks through sys.meta_path
, in similar approach this question. this, need define 2 functions find_module
, load_module
explained in link above. here load_module
function,
import imp def load_module(name, path): fp, pathname, description = imp.find_module(name, path) try: module = imp.load_module(name, fp, pathname, description) finally: if fp: fp.close() return module
which works fine modules, fails pyqt4.qtcore
when using python 2.7:
name = "qtcore" path = ['/usr/lib64/python2.7/site-packages/pyqt4'] mod = load_module(name, path)
which returns,
traceback (most recent call last): file "test.py", line 19, in <module> mod = load_module(name, path) file "test.py", line 13, in load_module module = imp.load_module(name, fp, pathname, description) systemerror: dynamic module not initialized
the same code works fine python 3.4 (although imp
getting deprecated , importlib
should ideally used instead there).
i suppose has sip dynamic module initialization. there else should try python 2.7?
note: applies both pyqt4
, pyqt5
.
edit: may related this question indeed,
cd /usr/lib64/python2.7/site-packages/pyqt4 python2 -c 'import qtcore'
fails same error. still i'm not sure way around it...
edit2: following @nikita's request concrete use case example, trying redirect import, when 1 import a
, happens import b
. 1 indeed think sufficient module renaming in find_spec/find_module
, use default load_module
. however, unclear find default load_module
implementation in python 2. closest implementation have found of similar future.standard_library.renameimport
. not there backport of complete implementation of importlib
python 3 2.
a minimal working example import hooks reproduces problem can found in gist.
upd: part in not relevant after answer updates, see upd below.
why not use importlib.import_module
, available in both python 2.7 , python 3:
#test.py import importlib mod = importlib.import_module('pyqt4.qtcore') print(mod.__file__)
on ubuntu 14.04:
$ python2 test.py /usr/lib/python2.7/dist-packages/pyqt4/qtcore.so
since it's dynamic module, said in error (and actual file qtcore.so
), may take @ imp.load_dynamic
.
another solution might force execution of module initialization code, imo it's of hassle, why not use importlib
.
upd: there things in pkgutil
, might help. talking in comment, try modify finder this:
import pkgutil class renameimportfinder(object): def find_module(self, fullname, path=none): """ finder function renames imports pyqt4.module or pyside.module pyqt4.module """ backend_name in valid_backends: if fullname.startswith(backend_name): # rename import (that's thought about) name_new = fullname.replace(backend_name, redirect_to_backend) print('renaming import:', fullname, '->', name_new, ) print(' path:', path) # (and here, don't create custom loader, 1 # system, either using 'pkgutil.get_loader' suggested # in pep302, or instantiate 'pkgutil.imploader'). return pkgutil.get_loader(name_new) #(original return statement, 'pkgutil.imploader' #instantiation should inside 'renameimportloader' after #'find_module()' call.) #return renameimportloader(name_orig=fullname, path=path, # name_new=name_new) return none
can't test code above now, please try yourself.
p.s. note imp.load_module()
, worked in python 3 deprecated since python 3.3.
another solution not use hooks @ all, instead wrap __import__
:
print(__import__) valid_backends = ['shelve'] redirect_to_backend = 'pickle' # using closure parameters def import_wrapper(valid_backends, redirect_to_backend): def wrapper(import_orig): def import_mod(*args, **kwargs): fullname = args[0] backend_name in valid_backends: if fullname.startswith(backend_name): fullname = fullname.replace(backend_name, redirect_to_backend) args = (fullname,) + args[1:] return import_orig(*args, **kwargs) return import_mod return wrapper # here it's important assign __import__ in __builtin__ , not # local __import__, or won't affect import statement. import __builtin__ __builtin__.__import__ = import_wrapper(valid_backends, redirect_to_backend)(__builtin__.__import__) print(__import__) import shutil import shelve import re import glob print shutil.__file__ print shelve.__file__ print re.__file__ print glob.__file__
output:
<built-in function __import__> <function import_mod @ 0x02bbcaf0> c:\python27\lib\shutil.pyc c:\python27\lib\pickle.pyc c:\python27\lib\re.pyc c:\python27\lib\glob.pyc
shelve
renamed pickle
, , pickle
imported default machinery variable name shelve
.
Comments
Post a Comment