10.3 使用相对路径å��导入包ä¸å�模å�—¶
问题¶
将代ç �组织æˆ�包,想用importè¯å�¥ä»Žå�¦ä¸€ä¸ªåŒ…å��没有硬编ç �过的包ä¸å¯¼å…¥å�模å�—。
解决方案¶
使用包的相对导入,使一个模å�—导入å�Œä¸€ä¸ªåŒ…çš„å�¦ä¸€ä¸ªæ¨¡å�— 举个例å�,å�‡è®¾åœ¨ä½ 的文件系统上有mypackage包,组织如下:
mypackage/
__init__.py
A/
__init__.py
spam.py
grok.py
B/
__init__.py
bar.py
如果模å�—mypackage.A.spamè¦�导入å�Œç›®å½•下的模å�—grok,它应该包括的importè¯å�¥å¦‚下:
# mypackage/A/spam.py
from . import grok
如果模å�—mypackage.A.spamè¦�导入ä¸�å�Œç›®å½•下的模å�—B.bar,它应该使用的importè¯å�¥å¦‚下:
# mypackage/A/spam.py
from ..B import bar
两个importè¯å�¥éƒ½æ²¡åŒ…å�«é¡¶å±‚包å��,而是使用了spam.py的相对路径。
讨论¶
在包内,既å�¯ä»¥ä½¿ç”¨ç›¸å¯¹è·¯å¾„也å�¯ä»¥ä½¿ç”¨ç»�对路径æ�¥å¯¼å…¥ã€‚ 举个例å�:
# mypackage/A/spam.py
from mypackage.A import grok # OK
from . import grok # OK
import grok # Error (not found)
åƒ�mypackage.Aè¿™æ ·ä½¿ç”¨ç»�对路径å��çš„ä¸�利之处是这将顶层包å��硬编ç �åˆ°ä½ çš„æº�ç �ä¸ã€‚å¦‚æžœä½ æƒ³é‡�æ–°ç»„ç»‡å®ƒï¼Œä½ çš„ä»£ç �将更脆,很难工作。 举个例å�ï¼Œå¦‚æžœä½ æ”¹å�˜äº†åŒ…å��ï¼Œä½ å°±å¿…é¡»æ£€æŸ¥æ‰€æœ‰æ–‡ä»¶æ�¥ä¿®æ£æº�ç �。 å�Œæ ·ï¼Œç¡¬ç¼–ç �çš„å��称会使移动代ç �å�˜å¾—困难。举个例å�,也许有人想安装两个ä¸�å�Œç‰ˆæœ¬çš„软件包,å�ªé€šè¿‡å��称区分它们。 如果使用相对导入,那一切都ok,然而使用ç»�对路径å��很å�¯èƒ½ä¼šå‡ºé—®é¢˜ã€‚
importè¯å�¥çš„ . å’Œ .. 看起æ�¥å¾ˆæ»‘稽, 但它指定目录å��.为当å‰�目录,..B为目录../B。这ç§�è¯æ³•å�ªé€‚用于import。
举个例å�:
from . import grok # OK
import .grok # ERROR
尽管使用相对导入看起æ�¥åƒ�是æµ�览文件系统,但是ä¸�能到定义包的目录之外。也就是说,使用点的这ç§�模å¼�从ä¸�是包的目录ä¸å¯¼å…¥å°†ä¼šå¼•å�‘错误。
最å�Žï¼Œç›¸å¯¹å¯¼å…¥å�ªé€‚用于在å�ˆé€‚的包ä¸çš„æ¨¡å�—。尤其是在顶层的脚本的简å�•模å�—ä¸ï¼Œå®ƒä»¬å°†ä¸�起作用。如果包的部分被作为脚本直接执行,那它们将ä¸�起作用 例如:
% python3 mypackage/A/spam.py # Relative imports fail
å�¦ä¸€æ–¹é�¢ï¼Œå¦‚æžœä½ ä½¿ç”¨Pythonçš„-m选项æ�¥æ‰§è¡Œå…ˆå‰�的脚本,相对导入将会æ£ç¡®è¿�行。 例如:
% python3 -m mypackage.A.spam # Relative imports work
更多的包的相对导入的背景知识,请看 PEP 328 .