问题
I'm trying to import PySide2 dynamically with importlib
, because statically with import
isn't sufficient for my application. I need importlib because in the end it will be used with pyinstaller to create a single executable that can import PySide2 dynamically, not just from the single executable.
I've copied an entire PySide2 package directory that was downloaded with pip. This PySide2 version is older than the one that I'm using by default, and when the "PySide2" directory is present in my source directory, I want to use it instead.
Based on the answer in this post, I have the following code to perform the import:
import os, sys
print("Import test")
if os.path.isdir('./PySide2/'):
print('Importing local PySide2')
import importlib.util
MODULE_PATH = "./PySide2/__init__.py"
MODULE_NAME = "PySide2"
spec = importlib.util.spec_from_file_location(MODULE_NAME, MODULE_PATH)
print("spec.name is " + str(spec.name))
module = importlib.util.module_from_spec(spec)
sys.modules[spec.name] = module
print(sys.modules)
spec.loader.exec_module(module)
print(PySide2.__version__)
else:
print('Importing system PySide2')
import PySide2
print(PySide2.__version__)
But when I run it, I get NameError: name 'PySide2' is not defined
, even though I see in sys.modules that PySide2 is present (scroll all the way to the right in the output below to see it is present):
$ python importTest.py
Import test
Importing local PySide2
spec.name is PySide2
{'sys': <module 'sys' (built-in)>, 'builtins': <module 'builtins' (built-in)>, '_frozen_importlib': <module 'importlib._bootstrap' (frozen)>, '_imp': <module '_imp' (built-in)>, '_thread': <module '_thread' (built-in)>, '_warnings': <module '_warnings' (built-in)>, '_weakref': <module '_weakref' (built-in)>, 'zipimport': <module 'zipimport' (built-in)>, '_frozen_importlib_external': <module 'importlib._bootstrap_external' (frozen)>, '_io': <module 'io' (built-in)>, 'marshal': <module 'marshal' (built-in)>, 'posix': <module 'posix' (built-in)>, 'encodings': <module 'encodings' from '/usr/lib/python3.7/encodings/__init__.py'>, 'codecs': <module 'codecs' from '/usr/lib/python3.7/codecs.py'>, '_codecs': <module '_codecs' (built-in)>, 'encodings.aliases': <module 'encodings.aliases' from '/usr/lib/python3.7/encodings/aliases.py'>, 'encodings.utf_8': <module 'encodings.utf_8' from '/usr/lib/python3.7/encodings/utf_8.py'>, '_signal': <module '_signal' (built-in)>, '__main__': <module '__main__' from 'importTest.py'>, 'encodings.latin_1': <module 'encodings.latin_1' from '/usr/lib/python3.7/encodings/latin_1.py'>, 'io': <module 'io' from '/usr/lib/python3.7/io.py'>, 'abc': <module 'abc' from '/usr/lib/python3.7/abc.py'>, '_abc': <module '_abc' (built-in)>, 'site': <module 'site' from '/usr/lib/python3.7/site.py'>, 'os': <module 'os' from '/usr/lib/python3.7/os.py'>, 'stat': <module 'stat' from '/usr/lib/python3.7/stat.py'>, '_stat': <module '_stat' (built-in)>, 'posixpath': <module 'posixpath' from '/usr/lib/python3.7/posixpath.py'>, 'genericpath': <module 'genericpath' from '/usr/lib/python3.7/genericpath.py'>, 'os.path': <module 'posixpath' from '/usr/lib/python3.7/posixpath.py'>, '_collections_abc': <module '_collections_abc' from '/usr/lib/python3.7/_collections_abc.py'>, '_sitebuiltins': <module '_sitebuiltins' from '/usr/lib/python3.7/_sitebuiltins.py'>, 'sitecustomize': <module 'sitecustomize' from '/usr/lib/python3.7/sitecustomize.py'>, 'importlib': <module 'importlib' from '/usr/lib/python3.7/importlib/__init__.py'>, 'importlib._bootstrap': <module 'importlib._bootstrap' (frozen)>, 'importlib._bootstrap_external': <module 'importlib._bootstrap_external' (frozen)>, 'types': <module 'types' from '/usr/lib/python3.7/types.py'>, 'warnings': <module 'warnings' from '/usr/lib/python3.7/warnings.py'>, 'importlib.util': <module 'importlib.util' from '/usr/lib/python3.7/importlib/util.py'>, 'importlib.abc': <module 'importlib.abc' from '/usr/lib/python3.7/importlib/abc.py'>, 'importlib.machinery': <module 'importlib.machinery' from '/usr/lib/python3.7/importlib/machinery.py'>, 'contextlib': <module 'contextlib' from '/usr/lib/python3.7/contextlib.py'>, 'collections': <module 'collections' from '/usr/lib/python3.7/collections/__init__.py'>, 'operator': <module 'operator' from '/usr/lib/python3.7/operator.py'>, '_operator': <module '_operator' (built-in)>, 'keyword': <module 'keyword' from '/usr/lib/python3.7/keyword.py'>, 'heapq': <module 'heapq' from '/usr/lib/python3.7/heapq.py'>, '_heapq': <module '_heapq' (built-in)>, 'itertools': <module 'itertools' (built-in)>, 'reprlib': <module 'reprlib' from '/usr/lib/python3.7/reprlib.py'>, '_collections': <module '_collections' (built-in)>, 'functools': <module 'functools' from '/usr/lib/python3.7/functools.py'>, '_functools': <module '_functools' (built-in)>, 'PySide2': <module 'PySide2' from './PySide2/__init__.py'>}
Traceback (most recent call last):
File "importTest.py", line 17, in <module>
print(PySide2.__version__)
NameError: name 'PySide2' is not defined
I don't understand why it says "name 'PySide2' is not define" when it appears in the sys.modules.
回答1:
From the documentation, NameError
is raised when a local or global name is not found.
For the standard import statement, it will do following things:
- Find & Load the module
- Update sys.modules
- Update global dict with a variable name pointing to actual module object for
import foo
, update multiple variables when it'simport * from something
(also check__all__
of the module)
Here you've already done the first 2 steps manually, you only need to add:
PySide2 = module
来源:https://stackoverflow.com/questions/56615123/python-use-importlib-to-import-a-module-from-a-package-directory