5. 北京/上海/⼲⼴广州 0xFF Life's pathetic, go Pythonic!
relative_import
代码⽰示例:
from .foo import bar
from ..foo import bar
• 在 py2.7 之前是python的默认的module引⼊入⽅方式
• 推荐阅读:PEP0328
6. 北京/上海/⼲⼴广州 0xFF Life's pathetic, go Pythonic!
absolute Import
代码⽰示例:
from __future__ import absolute_import
from API.foo import bar
from API.API2.foo import bar
• 在py2.5实现,需要明确的声明从 __future__ 中引⼊入该机制。在py2.7和
py3中成为默认的引⼊入机制。
11. 北京/上海/⼲⼴广州 0xFF Life's pathetic, go Pythonic!
⼩小知识:加载python的⼆二
种⽅方式
• as the top-level script
python foo/myfile.py
• as a module:
python -m foo.myfile
12. 北京/上海/⼲⼴广州 0xFF Life's pathetic, go Pythonic!
⼆二种加载⽅方式的不同之
处
When a file is loaded, it is given a name (which is
stored in its __name__ attribute). If it was loaded as
the top-level script, its name is __main__. If it was
loaded as a module, its name is the filename,
preceded by the names of any packages/
subpackages of which it is a part, separated by dots.
• 推荐阅读:http://stackoverflow.com/questions/
14132789/pythonrelative-imports-for-the-billionth-
time
14. 北京/上海/⼲⼴广州 0xFF Life's pathetic, go Pythonic!
出错的原因
• 当使⽤用⽤用python subpackage1/foo.py时,foo.py 被当成了
top level script,它的__name__属性被设置为__main__。
• relative import则是根据__name__来确定被引⼊入⼊入包的位
置。
Relative imports use a module's __name__ attribute to
determine that module's position in the package hierarchy. If
the module’s name does not contain any package
information (e.g. it is set to '__main__') then relative imports
are resolved as if the module were a top level module,
regardless of where the module is actually located on the file
system.
39. 北京/上海/⼲⼴广州 0xFF Life's pathetic, go Pythonic!
flask 实现
def load_module(self, fullname):
if fullname in sys.modules:
return sys.modules[fullname]
modname = fullname.split('.', self.prefix_cutoff)[self.prefix_cutoff]
for path in self.module_choices:
realname = path % modname
try:
__import__(realname)
except ImportError:
exc_type, exc_value, tb = sys.exc_info()
sys.modules.pop(fullname, None)
if self.is_important_traceback(realname, tb):
reraise(exc_type, exc_value, tb.tb_next)
continue
module = sys.modules[fullname] = sys.modules[realname]
if '.' not in modname:
setattr(sys.modules[self.wrapper_module], modname, module)
return module
raise ImportError('No module named %s' % fullname)
40. 北京/上海/⼲⼴广州 0xFF Life's pathetic, go Pythonic!
Hook Example5
>>> import requests
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: No module named ‘requests'
>>> import autoinstall
>>> import requests
Installing requests
>>> requests
<module 'requests' from '...python3.4/site-packages/requests/
__init__.py’>
在import第三⽅方包时,⾃自动安装相应的依赖
41. 北京/上海/⼲⼴广州 0xFF Life's pathetic, go Pythonic!
import sys
import subprocess
import importlib.util
class AutoInstall(object):
_loaded = set()
@classmethod
def find_spec(cls, name, path, target=None):
if path is None!and name not in! cls._loaded:
cls._loaded.add(name)
print("Installing",! name)
try:
out = subprocess.check_output(
[sys.executable, '-m', 'pip', 'install', name])
return importlib.util.find_spec(name)
except Exception as e:
print("Failed")
return None
sys.meta_path.append(AutoInstall)
42. 北京/上海/⼲⼴广州 0xFF Life's pathetic, go Pythonic!
Refrences
• Modules and Packages:Live and Let Die! —David Beazley
• http://stackoverflow.com/questions/14132789/pythonrelative-imports-for-the-billionth-time
• https://github.com/tornadoweb/tornado
• https://github.com/mitsuhiko/flask
• PEP 0328
• PEP 0273
• PEP 0338
• PEP 0008
• PEP 0302
• PEP 0366
• PEP 0451