Skip to content

Commit 24f5fa1

Browse files
committed
Update LEARNING/IMPORT
1 parent e5e97f1 commit 24f5fa1

File tree

35 files changed

+606
-0
lines changed

35 files changed

+606
-0
lines changed
+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from pkg import run

LEARNING/IMPORT/0_AbsoluteImport/pkg/__init__.py

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
print(__name__)
2+
print(__package__)
3+
4+
a = 2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
print(__name__)
2+
print(__package__)
3+
4+
from pkg.foo import a
5+
print(a)
6+
7+
from pkg.sub.bar import b
8+
print(b)

LEARNING/IMPORT/0_AbsoluteImport/pkg/sub/__init__.py

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
print(__name__)
2+
print(__package__)
3+
4+
b = 3
+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from pkg import run

LEARNING/IMPORT/0_RelativeImport/pkg/__init__.py

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
print(__name__)
2+
print(__package__)
3+
4+
a = 2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
print(__name__)
2+
print(__package__)
3+
4+
from .foo import a
5+
print(a)
6+
7+
from .sub.bar import b
8+
print(b)

LEARNING/IMPORT/0_RelativeImport/pkg/sub/__init__.py

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
print(__name__)
2+
print(__package__)
3+
4+
b = 3

LEARNING/IMPORT/1_Finder/pkg/__init__.py

Whitespace-only changes.
+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
print("pkg.sub.foo")

LEARNING/IMPORT/1_Finder/run.py

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import sys
2+
3+
class MyFinder(object):
4+
@classmethod
5+
def find_module(cls, name, path, target=None):
6+
print("Importing", name, path, target)
7+
return None
8+
9+
sys.meta_path.insert(0, MyFinder)
10+
11+
# import socket
12+
import pkg.sub.foo

LEARNING/IMPORT/1_ModuleSpec/foo.py

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
string = 'spec'

LEARNING/IMPORT/1_ModuleSpec/run.py

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
import foo
2+
print(foo.__spec__)

LEARNING/IMPORT/1_Reload/foo.py

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
print('reload')

LEARNING/IMPORT/1_Reload/run.py

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import importlib
2+
import foo
3+
import foo
4+
print('======')
5+
import pdb
6+
pdb.set_trace() # 设置断点
7+
importlib.reload(foo)

LEARNING/IMPORT/3_AutoInstall/core.py

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import sys
2+
import subprocess
3+
from importlib import import_module
4+
5+
# Debugging
6+
import logging
7+
logging.basicConfig(format='%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s',
8+
level=logging.DEBUG)
9+
logger = logging.getLogger(__name__)
10+
11+
12+
class AutoInstall(object):
13+
_loaded = set()
14+
15+
@classmethod
16+
def find_module(cls, name, path=None, target=None):
17+
logger.debug("Find module: name=%s, path=%s", name, path)
18+
if path is None and name not in cls._loaded:
19+
cls._loaded.add(name)
20+
logger.debug("Find module: installing %s", name)
21+
try:
22+
out = subprocess.check_output([sys.executable, '-m', 'pip', 'install', name])
23+
logger.debug("Find module: out=%r", out.decode('utf-8'))
24+
except Exception as e:
25+
logger.debug("Find module: install failed. %s", e)
26+
return None
27+
28+
logger.debug("Meta path: add finder `AutoInstall`")
29+
sys.meta_path.append(AutoInstall)

LEARNING/IMPORT/3_AutoInstall/main.py

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import logging
2+
import sys
3+
4+
import core
5+
6+
logger = logging.getLogger()
7+
logger.setLevel("DEBUG")
8+
9+
10+
logger.info("Import module tornado")
11+
try:
12+
import tornado
13+
except:
14+
import tornado
15+
logger.info("Install module tornado")
16+
17+
logger.info(tornado.__name__)
18+
logger.info(tornado.__doc__)
19+
20+
logger.info("Done")

LEARNING/IMPORT/3_LazyImport/core.py

+61
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import sys
2+
3+
from importlib import import_module
4+
from importlib.abc import Finder, Loader
5+
from importlib.machinery import ModuleSpec
6+
7+
8+
# Debugging
9+
import logging
10+
logging.basicConfig(format='%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s',
11+
level=logging.DEBUG)
12+
logger = logging.getLogger(__name__)
13+
14+
class LazyFinder(Finder):
15+
_lazy_modules = { }
16+
17+
@classmethod
18+
def find_spec(cls, fullname, path=None, target=None):
19+
spec = cls._lazy_modules.get(fullname, None)
20+
if spec and spec.import_please:
21+
logger.debug(f"Attribute in module '{fullname}' requested, actually importing")
22+
# Returning None means we skip this finder.
23+
return None
24+
spec = ModuleSpec(fullname, LazyLoader())
25+
cls._lazy_modules[fullname] = spec
26+
return spec
27+
28+
29+
class LazyLoader(Loader):
30+
def create_module(self, spec):
31+
return LazyModule(spec)
32+
33+
def exec_module(self, module):
34+
return module
35+
36+
37+
class LazyModule:
38+
def __init__(self, spec):
39+
self.spec = spec
40+
self.imported = False
41+
42+
def _import(self):
43+
self.spec.import_please = True
44+
del sys.modules[self.spec.name]
45+
self.module = import_module(self.spec.name)
46+
sys.modules[self.spec.name] = self.module
47+
# TODO After this, the LazyModule is still bound.
48+
# Since I set it here, the import machinery must do it after.
49+
self.imported = True
50+
51+
def __getattr__(self, attr):
52+
if self.imported:
53+
pass
54+
# It'd be great to avoid it trying to import this in the first place.
55+
elif attr in ["__name__", "__loader__", "__package__", "__path__"]:
56+
return None
57+
elif not self.imported:
58+
self._import()
59+
return self.module.__getattribute__(attr)
60+
61+
sys.meta_path = sys.meta_path[:-1] + [LazyFinder] + sys.meta_path[-1:]

LEARNING/IMPORT/3_LazyImport/main.py

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import logging
2+
import sys
3+
4+
import core
5+
6+
logger = logging.getLogger()
7+
logger.setLevel("DEBUG")
8+
9+
logger.info("Importing module small")
10+
import small
11+
logger.info("Module small 'imported'")
12+
13+
logger.info(small.x)
14+
logger.info(small.__name__)
15+
16+
logger.info("Done")

LEARNING/IMPORT/3_LazyImport/small.py

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import logging
2+
import time
3+
4+
logger = logging.getLogger()
5+
logger.setLevel("DEBUG")
6+
7+
logger.info("Sleeping!")
8+
time.sleep(1)
9+
logger.info("Done sleeping!")
10+
11+
x = "Hello from small!"

LEARNING/IMPORT/3_LazyImport/test.py

+67
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import logging
2+
import sys
3+
4+
from importlib import import_module
5+
from importlib.abc import Finder, Loader
6+
from importlib.machinery import ModuleSpec
7+
8+
9+
logger = logging.getLogger()
10+
logger.setLevel(logging.DEBUG)
11+
formatter = logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")
12+
handler = logging.StreamHandler()
13+
handler.setFormatter(formatter)
14+
logger.addHandler(handler)
15+
16+
class LazyFinder(Finder):
17+
_lazy_modules = { }
18+
19+
@classmethod
20+
def find_spec(cls, fullname, path=None, target=None):
21+
spec = cls._lazy_modules.get(fullname, None)
22+
if spec:
23+
logger.debug(f"Attribute in module '{fullname}' requested, actually importing")
24+
return None
25+
spec = ModuleSpec(fullname, LazyLoader())
26+
cls._lazy_modules[fullname] = spec
27+
return spec
28+
29+
30+
class LazyLoader(Loader):
31+
def create_module(self, spec):
32+
return LazyModule(spec)
33+
34+
def exec_module(self, module):
35+
return module
36+
37+
38+
class LazyModule:
39+
def __init__(self, spec):
40+
self.spec = spec
41+
self.imported = False
42+
43+
def _import(self):
44+
del sys.modules[self.spec.name]
45+
self.module = import_module(self.spec.name)
46+
sys.modules[self.spec.name] = self.module
47+
self.imported = True
48+
49+
def __getattr__(self, attr):
50+
if attr in ["__name__", "__loader__", "__package__", "__path__"]:
51+
return None
52+
elif not self.imported:
53+
self._import()
54+
return self.module.__getattribute__(attr)
55+
56+
sys.meta_path = sys.meta_path[:-1] + [LazyFinder] + sys.meta_path[-1:]
57+
58+
59+
if __name__ == '__main__':
60+
logger.info("Do Lazy Import")
61+
62+
logger.info("Importing module small")
63+
import small
64+
logger.info("Module small 'imported'")
65+
logger.info(small.x)
66+
logger.info(small.__name__)
67+
logger.info("Done")

LEARNING/IMPORT/3_RemoteLoad/base.py

+95
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
import sys
2+
from importlib import abc
3+
from importlib.machinery import ModuleSpec
4+
import imp
5+
from urllib.request import urlopen
6+
7+
# Debugging
8+
import logging
9+
logging.basicConfig(format='%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s',
10+
level=logging.DEBUG)
11+
logger = logging.getLogger(__name__)
12+
13+
14+
def load_module(url):
15+
logger.debug("Load module: get source from %s", url)
16+
u = urlopen(url)
17+
s = u.read().decode('utf-8')
18+
logger.debug("Load module: create module %s", url)
19+
m = sys.modules.setdefault(url, imp.new_module(url))
20+
c = compile(s, url, 'exec')
21+
m.__file__ = url
22+
m.__package__ = ''
23+
logger.debug("Load module: exec code object %s", c)
24+
exec(c, m.__dict__)
25+
return m
26+
27+
class UrlMetaFinder(abc.MetaPathFinder):
28+
def __init__(self, baseurl):
29+
self._baseurl = baseurl
30+
31+
def find_module(self, fullname, path=None):
32+
logger.debug("Find module: fullname=%s, path=%s", fullname, path)
33+
if path is None:
34+
baseurl = self._baseurl
35+
else:
36+
if not path.startswith(self._baseurl):
37+
return None
38+
baseurl = path
39+
try:
40+
logger.debug("Find module: module %s found", fullname)
41+
loader = UrlMetaLoader(baseurl)
42+
return loader
43+
except Exception:
44+
logger.debug("Find module: module %s not found", fullname)
45+
return None
46+
47+
# def find_spec(self, fullname, path=None, target=None):
48+
# if path is None:
49+
# baseurl = self._baseurl
50+
# else:
51+
# if not path.startswith(self._baseurl):
52+
# return None
53+
# baseurl = path
54+
# try:
55+
# loader = UrlMetaLoader(baseurl)
56+
# return ModuleSpec(fullname, loader, is_package=loader.is_package(fullname))
57+
# except Exception:
58+
# return None
59+
60+
61+
class UrlMetaLoader(abc.SourceLoader):
62+
def __init__(self, baseurl):
63+
self._baseurl = baseurl
64+
65+
# def load_module(self, fullname):
66+
# c = self.get_code(fullname)
67+
# m = sys.modules.setdefault(fullname, imp.new_module(fullname))
68+
# m.__file__ = self.get_filename(fullname)
69+
# m.__loader__ = self
70+
# m.__package__ = fullname
71+
# exec(c, m.__dict__)
72+
# return None
73+
74+
def get_code(self, fullname):
75+
u = urlopen(self.get_filename(fullname))
76+
return u.read()
77+
78+
# def execute_module(self, module):
79+
# pass
80+
81+
def get_data(self):
82+
pass
83+
84+
def get_filename(self, fullname):
85+
return self._baseurl + fullname + '.py'
86+
87+
def install_meta(address):
88+
finder = UrlMetaFinder(address)
89+
sys.meta_path.append(finder)
90+
logger.debug('%s installed on sys.meta_path', finder)
91+
92+
93+
if __name__ == '__main__':
94+
print("Base Url Import.")
95+

0 commit comments

Comments
 (0)