Skip to content

Commit 4fd79e6

Browse files
committed
Add playground.ipynb
1 parent 6c85a87 commit 4fd79e6

File tree

2 files changed

+191
-0
lines changed

2 files changed

+191
-0
lines changed

README.md

+4
Original file line numberDiff line numberDiff line change
@@ -33,5 +33,9 @@ else:
3333
raise ModuleNotFoundError
3434
```
3535

36+
## Experiments
37+
38+
See [playground.ipynb](./playground.ipynb) for some experiments on the diagram.
39+
3640
[1]: https://docs.python.org/3/reference/import.html
3741

playground.ipynb

+187
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
{
2+
"metadata": {
3+
"language_info": {
4+
"codemirror_mode": {
5+
"name": "ipython",
6+
"version": 3
7+
},
8+
"file_extension": ".py",
9+
"mimetype": "text/x-python",
10+
"name": "python",
11+
"nbconvert_exporter": "python",
12+
"pygments_lexer": "ipython3",
13+
"version": "3.7.8-final"
14+
},
15+
"orig_nbformat": 2,
16+
"kernelspec": {
17+
"name": "python3",
18+
"display_name": "Python 3",
19+
"language": "python"
20+
}
21+
},
22+
"nbformat": 4,
23+
"nbformat_minor": 2,
24+
"cells": [
25+
{
26+
"source": [
27+
"### `None` in sys.modules"
28+
],
29+
"cell_type": "markdown",
30+
"metadata": {}
31+
},
32+
{
33+
"cell_type": "code",
34+
"execution_count": 1,
35+
"metadata": {},
36+
"outputs": [
37+
{
38+
"output_type": "error",
39+
"ename": "ModuleNotFoundError",
40+
"evalue": "import of module halted; None in sys.modules",
41+
"traceback": [
42+
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
43+
"\u001b[0;31mModuleNotFoundError\u001b[0m Traceback (most recent call last)",
44+
"\u001b[0;32m<ipython-input-1-20156aa94da0>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0msys\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmodules\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'module'\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 4\u001b[0;31m \u001b[0;32mimport\u001b[0m \u001b[0mmodule\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
45+
"\u001b[0;31mModuleNotFoundError\u001b[0m: import of module halted; None in sys.modules"
46+
]
47+
}
48+
],
49+
"source": [
50+
"import sys\n",
51+
"sys.modules['module'] = None\n",
52+
"\n",
53+
"import module"
54+
]
55+
},
56+
{
57+
"source": [
58+
"### `sys.meta_path` exhausted"
59+
],
60+
"cell_type": "markdown",
61+
"metadata": {}
62+
},
63+
{
64+
"source": [
65+
"del sys.modules['module']\n",
66+
"del sys.meta_path[:]\n",
67+
"\n",
68+
"import module"
69+
],
70+
"cell_type": "code",
71+
"metadata": {},
72+
"execution_count": 2,
73+
"outputs": [
74+
{
75+
"output_type": "error",
76+
"ename": "ModuleNotFoundError",
77+
"evalue": "No module named 'module'",
78+
"traceback": [
79+
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
80+
"\u001b[0;31mModuleNotFoundError\u001b[0m Traceback (most recent call last)",
81+
"\u001b[0;32m<ipython-input-2-fd1bf8284402>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0;32mdel\u001b[0m \u001b[0msys\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmeta_path\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 4\u001b[0;31m \u001b[0;32mimport\u001b[0m \u001b[0mmodule\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
82+
"\u001b[0;31mModuleNotFoundError\u001b[0m: No module named 'module'"
83+
]
84+
}
85+
]
86+
},
87+
{
88+
"source": [
89+
"### Spec's loader is `None`"
90+
],
91+
"cell_type": "markdown",
92+
"metadata": {}
93+
},
94+
{
95+
"cell_type": "code",
96+
"execution_count": 7,
97+
"metadata": {},
98+
"outputs": [
99+
{
100+
"output_type": "error",
101+
"ename": "ImportError",
102+
"evalue": "missing loader",
103+
"traceback": [
104+
"\u001b[0;31m---------------------------------------------------------------------------\u001b[0m",
105+
"\u001b[0;31mImportError\u001b[0m Traceback (most recent call last)",
106+
"\u001b[0;32m<ipython-input-7-85f7fa80cfc0>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m\u001b[0m\n\u001b[1;32m 9\u001b[0m \u001b[0msys\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmeta_path\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0mfinder\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 10\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 11\u001b[0;31m \u001b[0;32mimport\u001b[0m \u001b[0mmodule\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m",
107+
"\u001b[0;31mImportError\u001b[0m: missing loader"
108+
]
109+
}
110+
],
111+
"source": [
112+
"from importlib.abc import MetaPathFinder\n",
113+
"from importlib.machinery import ModuleSpec\n",
114+
"\n",
115+
"class NoLoaderFinder(MetaPathFinder):\n",
116+
" def find_spec(self, fullname, path, target=None):\n",
117+
" return ModuleSpec('module', None)\n",
118+
"\n",
119+
"finder = NoLoaderFinder()\n",
120+
"sys.meta_path = [finder]\n",
121+
"\n",
122+
"import module"
123+
]
124+
},
125+
{
126+
"source": [
127+
"### Regular loader"
128+
],
129+
"cell_type": "markdown",
130+
"metadata": {}
131+
},
132+
{
133+
"cell_type": "code",
134+
"execution_count": 17,
135+
"metadata": {},
136+
"outputs": [
137+
{
138+
"output_type": "stream",
139+
"name": "stdout",
140+
"text": [
141+
"module <module 'module' (<__main__.ExampleLoader object at 0x7f782ed6e3d0>)>\nmodule.name module\nmodule.x 1\nmodule.y 2\n----------\nmodule2 is module? False\nmodule2 <module 'module' (<__main__.ExampleLoader object at 0x7f782deab5d0>)>\nmodule2.name module\nmodule2.x 1\nmodule2.y 2\n"
142+
]
143+
}
144+
],
145+
"source": [
146+
"from types import ModuleType\n",
147+
"from importlib.abc import Loader\n",
148+
"\n",
149+
"class Module(ModuleType):\n",
150+
" def __init__(self, name):\n",
151+
" self.x = 1\n",
152+
" self.name = name\n",
153+
"\n",
154+
"class ExampleLoader(Loader):\n",
155+
" def create_module(self, spec):\n",
156+
" return Module(spec.name)\n",
157+
"\n",
158+
" def exec_module(self, module):\n",
159+
" module.y = 2\n",
160+
"\n",
161+
"class ExampleFinder(MetaPathFinder):\n",
162+
" def find_spec(self, fullname, path, target=None):\n",
163+
" return ModuleSpec('module', ExampleLoader())\n",
164+
"\n",
165+
"sys.meta_path = [ExampleFinder()]\n",
166+
"\n",
167+
"import module\n",
168+
"print('module', module)\n",
169+
"print('module.name', module.name)\n",
170+
"print('module.x', module.x)\n",
171+
"print('module.y', module.y)\n",
172+
"\n",
173+
"del sys.modules['module']\n",
174+
"\n",
175+
"print('-' * 10)\n",
176+
"module2 = __import__('module')\n",
177+
"\n",
178+
"print('module2 is module?', module2 is module)\n",
179+
"print('module2', module2)\n",
180+
"print('module2.name', module2.name)\n",
181+
"print('module2.x', module2.x)\n",
182+
"print('module2.y', module2.y)\n",
183+
"\n"
184+
]
185+
}
186+
]
187+
}

0 commit comments

Comments
 (0)