Python 包导入:寻址子模块的规则是什么?
Python package imports: What's the rule for addressing submodules?
我有点困惑 python 如何知道包中的模块。例如,python-pptx
包有一个子模块 chart
,其目录结构为
tree /usr/local/lib/python2.7/site-packages/pptx/chart
/usr/local/lib/python2.7/site-packages/pptx/chart
├── __init__.py
├── axis.py
├── category.py
├── chart.py
├── data.py
├── datalabel.py
├── legend.py
├── marker.py
├── plot.py
├── point.py
├── series.py
├── xlsx.py
└── xmlwriter.py
现在如果我
import pptx
地址chart
为
dir(pptx.chart)
然后子模块 data
和 xlsx
丢失了
['__builtins__',
'__doc__',
'__file__',
'__name__',
'__package__',
'__path__',
'axis',
'category',
'chart',
'datalabel',
'legend',
'marker',
'plot',
'point',
'series',
'xmlwriter']
我可以使用 dir(pptx.chart.axis)
直接解决 pptx.chart.axis
但 dir(pptx.chart.data)
导致
AttributeError: 'module' object has no attribute 'data'
如果我 import pptx.chart
也会发生同样的事情
但我可以毫无问题地导入 pptx.chart.data
。
这里有什么包导入规则?
预计到达时间
Python dir() not displaying all modules in a package
是一个相关问题,但没有完全解决我的问题。
正如 Alex Hall 所解释的那样,这里改写了一些包和模块还加载了其他包和模块。例如,使用
python modulefinder.py test.py | grep pptx
我发现,除其他外,还加载了以下内容
P pptx.chart /usr/local/lib/python2.7/site-packages/pptx/chart/__init__.py
m pptx.chart.axis /usr/local/lib/python2.7/site-packages/pptx/chart/axis.py
m pptx.chart.category /usr/local/lib/python2.7/site-packages/pptx/chart/category.py
m pptx.chart.chart /usr/local/lib/python2.7/site-packages/pptx/chart/chart.py
m pptx.chart.datalabel /usr/local/lib/python2.7/site-packages/pptx/chart/datalabel.py
m pptx.chart.legend /usr/local/lib/python2.7/site-packages/pptx/chart/legend.py
m pptx.chart.marker /usr/local/lib/python2.7/site-packages/pptx/chart/marker.py
m pptx.chart.plot /usr/local/lib/python2.7/site-packages/pptx/chart/plot.py
m pptx.chart.point /usr/local/lib/python2.7/site-packages/pptx/chart/point.py
m pptx.chart.series /usr/local/lib/python2.7/site-packages/pptx/chart/series.py
m pptx.chart.xmlwriter /usr/local/lib/python2.7/site-packages/pptx/chart/xmlwriter.py
dir
仅列出已加载的函数,而由于 pptx
未加载 pptx.data
,因此 dir
未列出。要找到所有可能可加载的模块,必须使用 help
help(pptx.chart)
Help on package pptx.chart in pptx:
NAME
pptx.chart
FILE
/usr/local/lib/python2.7/site-packages/pptx/chart/__init__.py
PACKAGE CONTENTS
axis
category
chart
data
datalabel
legend
marker
plot
point
series
xlsx
xmlwriter
并且,如果需要包中的子模块,则应该显式加载它,而不是依赖于它已被其他东西加载的假设。这就是我要找的规则。
导入模块时,无论从何处导入,它们都会作为属性添加到父模块。如果它们不是从任何地方进口的,它们将不可用。这是因为创建模块是一个昂贵的过程,您只想创建您实际需要的模块。
某处(可能不是您直接导入,而是您直接或间接导入的模块之一)导入了 pptx.chart.axis
。
如果你想使用一个模块,导入它以保证它在那里。如果你没有显式导入它,如果它被导入到其他地方,它可能仍然存在,但它不可靠。
这是 Django 的实际效果:
>>> import sys
>>> [x for x in sys.modules if x.startswith('django')]
[]
>>> import django
>>> [x for x in sys.modules if x.startswith('django')]
['django.utils.version', 'django', 'django.utils.lru_cache', 'django.utils']
>>> django
<module 'django' from '/Users/alexhall/.pyenv/versions/3.5.1/lib/python3.5/site-packages/django/__init__.py'>
>>> django.utils
<module 'django.utils' from '/Users/alexhall/.pyenv/versions/3.5.1/lib/python3.5/site-packages/django/utils/__init__.py'>
>>> django.core
Traceback (most recent call last):
File "<input>", line 1, in <module>
AttributeError: module 'django' has no attribute 'core'
>>> django.db
Traceback (most recent call last):
File "<input>", line 1, in <module>
AttributeError: module 'django' has no attribute 'db'
>>> import django.db
>>> [x for x in sys.modules if x.startswith('django')]
['django.dispatch', 'django.dispatch.dispatcher', 'django.utils.six.moves', 'django.utils.encoding', 'django.utils.version', 'django.utils.six.moves.urllib', 'django.utils.module_loading', 'django.db', 'django.utils.six', 'django.db.utils', 'django.core.signals', 'django', 'django.utils.functional', 'django.core', 'django.utils.deprecation', 'django.utils.six.moves.urllib.parse', 'django.utils.lru_cache', 'django.conf', 'django.utils.inspect', 'django.utils._os', 'django.core.exceptions', 'django.utils', 'django.conf.global_settings']
>>> django.core
<module 'django.core' from '/Users/alexhall/.pyenv/versions/3.5.1/lib/python3.5/site-packages/django/core/__init__.py'>
>>> django.db
<module 'django.db' from '/Users/alexhall/.pyenv/versions/3.5.1/lib/python3.5/site-packages/django/db/__init__.py'>
我有点困惑 python 如何知道包中的模块。例如,python-pptx
包有一个子模块 chart
,其目录结构为
tree /usr/local/lib/python2.7/site-packages/pptx/chart
/usr/local/lib/python2.7/site-packages/pptx/chart
├── __init__.py
├── axis.py
├── category.py
├── chart.py
├── data.py
├── datalabel.py
├── legend.py
├── marker.py
├── plot.py
├── point.py
├── series.py
├── xlsx.py
└── xmlwriter.py
现在如果我
import pptx
地址chart
为
dir(pptx.chart)
然后子模块 data
和 xlsx
丢失了
['__builtins__',
'__doc__',
'__file__',
'__name__',
'__package__',
'__path__',
'axis',
'category',
'chart',
'datalabel',
'legend',
'marker',
'plot',
'point',
'series',
'xmlwriter']
我可以使用 dir(pptx.chart.axis)
直接解决 pptx.chart.axis
但 dir(pptx.chart.data)
导致
AttributeError: 'module' object has no attribute 'data'
如果我 import pptx.chart
但我可以毫无问题地导入 pptx.chart.data
。
这里有什么包导入规则?
预计到达时间
Python dir() not displaying all modules in a package
是一个相关问题,但没有完全解决我的问题。
正如 Alex Hall 所解释的那样,这里改写了一些包和模块还加载了其他包和模块。例如,使用
python modulefinder.py test.py | grep pptx
我发现,除其他外,还加载了以下内容
P pptx.chart /usr/local/lib/python2.7/site-packages/pptx/chart/__init__.py
m pptx.chart.axis /usr/local/lib/python2.7/site-packages/pptx/chart/axis.py
m pptx.chart.category /usr/local/lib/python2.7/site-packages/pptx/chart/category.py
m pptx.chart.chart /usr/local/lib/python2.7/site-packages/pptx/chart/chart.py
m pptx.chart.datalabel /usr/local/lib/python2.7/site-packages/pptx/chart/datalabel.py
m pptx.chart.legend /usr/local/lib/python2.7/site-packages/pptx/chart/legend.py
m pptx.chart.marker /usr/local/lib/python2.7/site-packages/pptx/chart/marker.py
m pptx.chart.plot /usr/local/lib/python2.7/site-packages/pptx/chart/plot.py
m pptx.chart.point /usr/local/lib/python2.7/site-packages/pptx/chart/point.py
m pptx.chart.series /usr/local/lib/python2.7/site-packages/pptx/chart/series.py
m pptx.chart.xmlwriter /usr/local/lib/python2.7/site-packages/pptx/chart/xmlwriter.py
dir
仅列出已加载的函数,而由于 pptx
未加载 pptx.data
,因此 dir
未列出。要找到所有可能可加载的模块,必须使用 help
help(pptx.chart)
Help on package pptx.chart in pptx:
NAME
pptx.chart
FILE
/usr/local/lib/python2.7/site-packages/pptx/chart/__init__.py
PACKAGE CONTENTS
axis
category
chart
data
datalabel
legend
marker
plot
point
series
xlsx
xmlwriter
并且,如果需要包中的子模块,则应该显式加载它,而不是依赖于它已被其他东西加载的假设。这就是我要找的规则。
导入模块时,无论从何处导入,它们都会作为属性添加到父模块。如果它们不是从任何地方进口的,它们将不可用。这是因为创建模块是一个昂贵的过程,您只想创建您实际需要的模块。
某处(可能不是您直接导入,而是您直接或间接导入的模块之一)导入了 pptx.chart.axis
。
如果你想使用一个模块,导入它以保证它在那里。如果你没有显式导入它,如果它被导入到其他地方,它可能仍然存在,但它不可靠。
这是 Django 的实际效果:
>>> import sys
>>> [x for x in sys.modules if x.startswith('django')]
[]
>>> import django
>>> [x for x in sys.modules if x.startswith('django')]
['django.utils.version', 'django', 'django.utils.lru_cache', 'django.utils']
>>> django
<module 'django' from '/Users/alexhall/.pyenv/versions/3.5.1/lib/python3.5/site-packages/django/__init__.py'>
>>> django.utils
<module 'django.utils' from '/Users/alexhall/.pyenv/versions/3.5.1/lib/python3.5/site-packages/django/utils/__init__.py'>
>>> django.core
Traceback (most recent call last):
File "<input>", line 1, in <module>
AttributeError: module 'django' has no attribute 'core'
>>> django.db
Traceback (most recent call last):
File "<input>", line 1, in <module>
AttributeError: module 'django' has no attribute 'db'
>>> import django.db
>>> [x for x in sys.modules if x.startswith('django')]
['django.dispatch', 'django.dispatch.dispatcher', 'django.utils.six.moves', 'django.utils.encoding', 'django.utils.version', 'django.utils.six.moves.urllib', 'django.utils.module_loading', 'django.db', 'django.utils.six', 'django.db.utils', 'django.core.signals', 'django', 'django.utils.functional', 'django.core', 'django.utils.deprecation', 'django.utils.six.moves.urllib.parse', 'django.utils.lru_cache', 'django.conf', 'django.utils.inspect', 'django.utils._os', 'django.core.exceptions', 'django.utils', 'django.conf.global_settings']
>>> django.core
<module 'django.core' from '/Users/alexhall/.pyenv/versions/3.5.1/lib/python3.5/site-packages/django/core/__init__.py'>
>>> django.db
<module 'django.db' from '/Users/alexhall/.pyenv/versions/3.5.1/lib/python3.5/site-packages/django/db/__init__.py'>