Ответ 1
UPD: эта часть не очень актуальна после ответов на ответы, поэтому см. UPD ниже.
Почему бы просто не использовать importlib.import_module
, который доступен как в Python 2.7, так и в Python 3:
#test.py
import importlib
mod = importlib.import_module('PyQt4.QtCore')
print(mod.__file__)
на Ubuntu 14.04:
$ python2 test.py
/usr/lib/python2.7/dist-packages/PyQt4/QtCore.so
Так как это динамический модуль, как сказано в ошибке (и фактический файл QtCore.so
), можно также взглянуть на imp.load_dynamic
.
Другим решением может быть принудительное выполнение кода инициализации модуля, но IMO это слишком много хлопот, так почему бы просто не использовать importlib
.
UPD. В pkgutil
есть вещи, которые могут помочь. О чем я говорил в своем комментарии, попробуйте изменить свой поиск следующим образом:
import pkgutil
class RenameImportFinder(object):
def find_module(self, fullname, path=None):
""" This is the finder function that renames all imports like
PyQt4.module or PySide.module into PyQt4.module """
for backend_name in valid_backends:
if fullname.startswith(backend_name):
# just rename the import (That what i 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 a custom loader, get one from the
# system, either by using 'pkgutil.get_loader' as suggested
# in PEP302, or instantiate 'pkgutil.ImpLoader').
return pkgutil.get_loader(name_new)
#(Original return statement, probably 'pkgutil.ImpLoader'
#instantiation should be inside 'RenameImportLoader' after
#'find_module()' call.)
#return RenameImportLoader(name_orig=fullname, path=path,
# name_new=name_new)
return None
Не удается проверить код выше, поэтому, пожалуйста, попробуйте сами.
P.S. Обратите внимание: imp.load_module()
, который работал на вас в Python 3, устарел с Python 3.3.
Другое решение - не использовать крючки вообще, а вместо этого обернуть __import__
:
print(__import__)
valid_backends = ['shelve']
redirect_to_backend = 'pickle'
# Using closure with parameters
def import_wrapper(valid_backends, redirect_to_backend):
def wrapper(import_orig):
def import_mod(*args, **kwargs):
fullname = args[0]
for 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 important to assign to __import__ in __builtin__ and not
# local __import__, or it won't affect the 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__
выход:
<built-in function __import__>
<function import_mod at 0x02BBCAF0>
C:\Python27\lib\shutil.pyc
C:\Python27\lib\pickle.pyc
C:\Python27\lib\re.pyc
C:\Python27\lib\glob.pyc
shelve
переименован в pickle
, а pickle
импортируется по умолчанию машиной с именем переменной shelve
.