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

Popular posts from this blog

java - nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet Hibernate+SpringMVC -

sql - Postgresql tables exists, but getting "relation does not exist" when querying -

asp.net mvc - breakpoint on javascript in CSHTML? -