未翻訳のページ
このページはまだ日本語に翻訳されていないため、英語の原文を表示しています。 翻訳に協力する
imp Module Complexity¶
imp is the pre-importlib API for finding and loading modules by hand.
Complexity Reference¶
Here, p is the number of directories searched, s the number of recognised
suffixes (the length of get_suffixes()), n the size in bytes of the file or
frozen code being loaded, L the length of a path string, b the number of
modules compiled into the interpreter, and f the number of frozen modules.
Loading a module also executes its body; that cost belongs to the module and is
not counted below. Space is auxiliary memory, excluding the module created.
| Operation | Time | Space | Notes |
|---|---|---|---|
find_module(name, path=None) |
O(p × s) | O(s) | Probes directories in order until one matches; path=None adds the O(b + f) table checks and searches all of sys.path; returns an open file after reading only its encoding lines |
load_source(name, pathname, file=None) |
O(n) | O(n) | Reads the whole file; a valid __pycache__ entry skips compilation |
load_compiled(name, pathname, file=None) |
O(n) | O(n) | Reads and unmarshals the whole .pyc |
load_package(name, path) |
O(n) | O(n) | Executes __init__ only; n is its size |
load_module(name, file, filename, details) |
O(1) | O(1) | Dispatches on the type code in details, then costs what that loader costs |
load_dynamic(name, path, file=None) |
O(1) | O(1) | Python-side work; dlopen and the extension's init function are the real cost |
reload(module) |
O(n) | O(n) | Plus the finders' cost: it re-finds the module through the import system, so one loaded from a directory it cannot see raises ModuleNotFoundError |
new_module(name) |
O(1) | O(1) | An empty module, not entered into sys.modules |
init_builtin(name) |
O(b) | O(1) | Scans the built-in table, then runs the module's init function |
init_frozen(name) |
O(f + n) | O(n) | Scans the frozen tables, then unmarshals the frozen code |
is_builtin(name) |
O(b) | O(1) | Scans the built-in table |
is_frozen(name) |
O(f) | O(1) | Scans the frozen tables |
get_magic() / get_tag() |
O(1) | O(1) | Return existing objects |
get_suffixes() |
O(s) | O(s) | Builds a fresh list on every call |
cache_from_source(path) / source_from_cache(path) |
O(L) | O(L) | String work only; the files need not exist |
lock_held() / acquire_lock() / release_lock() |
O(1) | O(1) | The global import lock; acquire_lock() blocks while another thread holds it |
NullImporter(path) |
O(1) | O(1) | One isdir check; its find_module() always returns None |
SEARCH_ERROR, PY_SOURCE, PY_COMPILED, C_EXTENSION, PY_RESOURCE, PKG_DIRECTORY, C_BUILTIN, PY_FROZEN, PY_CODERESOURCE, IMP_HOOK |
O(1) | O(1) | Module type codes 0 to 9 |
Removed in Python 3.12
Deprecated in Python 3.4 and removed in Python 3.12. This page covers the
API documented for Python 3.11 plus the undocumented load_source(),
load_compiled() and load_package() loaders. The _imp re-exports
create_dynamic, get_frozen_object and is_frozen_package, the
re-exported SourcelessFileLoader, and the modules imp imports are
outside its scope.
Finding a Module¶
find_module() stats each directory for a package and for every suffix
before moving to the next, so its cost is set by the search path rather than
by the module. Pass the package's __path__ or a short list as path instead
of letting it walk all of sys.path. Without path, the built-in and frozen
tables are consulted first and a hit there probes no directories.
Loading Source¶
load_source() runs the same SourceFileLoader code path as a normal import:
the first load compiles the source and, unless bytecode writing is disabled,
writes a .pyc under __pycache__; a later load whose cache is still valid
reads the bytecode instead of compiling. load_compiled() starts from the
.pyc directly and never compiles.
Run this example on Python 3.10 or 3.11.
import imp
from pathlib import Path
from tempfile import TemporaryDirectory
with TemporaryDirectory() as directory:
Path(directory, "greeting.py").write_text("MESSAGE = 'hello'\n")
file, pathname, details = imp.find_module("greeting", [directory]) # O(p * s)
with file:
module = imp.load_module("greeting", file, pathname, details) # O(n)
assert module.MESSAGE == "hello"
again = imp.load_source("greeting", pathname) # O(n), from the .pyc
assert again is module
Modern Replacement¶
importlib.util does the same linear work without the deprecated API and runs
on every supported version.
import importlib.util
from pathlib import Path
from tempfile import TemporaryDirectory
with TemporaryDirectory() as directory:
path = Path(directory, "greeting.py")
path.write_text("MESSAGE = 'hello'\n")
spec = importlib.util.spec_from_file_location("greeting", path)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module) # O(n)
assert module.MESSAGE == "hello"