Module Search
https://docs.python.org/3/tutorial/modules.html#the-module-search-path
当使用import语句时, 首先解析器会寻找内置的模块, 例如 os, sys
然后在sys.path路径列表中搜索
此列表由如下三个路径组成:
(1)输入脚本的当所在路径
(2)PYTHONPATH环境中指定的路径列表
(3)第三方安装依赖路径
When a module named
spam
is imported, the interpreter first searches for a built-in module with that name. If not found, it then searches for a file namedspam.py
in a list of directories given by the variablesys.path
.sys.path
is initialized from these locations:
The directory containing the input script (or the current directory when no file is specified).
PYTHONPATH
(a list of directory names, with the same syntax as the shell variablePATH
).The installation-dependent default.
当前路径下载module会被命中, 即使在库目录中有相同的module
After initialization, Python programs can modify
sys.path
. The directory containing the script being run is placed at the beginning of the search path, ahead of the standard library path.This means that scripts in that directory will be loaded instead of modules of the same name in the library directory.
This is an error unless the replacement is intended. See section Standard Modules for more information.
sys.path例子
['/mnt/c/Users/xiaohua/Desktop/test_project',
'/usr/local/bin',
'/root/.pyenv/versions/3.6.8/lib/python36.zip',
'/root/.pyenv/versions/3.6.8/lib/python3.6',
'/root/.pyenv/versions/3.6.8/lib/python3.6/lib-dynload',
'/root/.pyenv/versions/3.6.8/lib/python3.6/site-packages']
sys.path操作
https://blog.csdn.net/longlovefilm/article/details/99683873?utm_medium=distribute.pc_relevant_bbs_down.none-task--2~all~baidu_landing_v2~default-1.nonecase&depth_1-utm_source=distribute.pc_relevant_bbs_down.none-task--2~all~baidu_landing_v2~default-1.nonecase
修改pythonpath
vim /etc/profile export PYTHONPATH=/home/www/oadata.xesv5.com source /etc/profile #每个打开的shell界面都要source起作用
添加再sys.path最前面
import sys sys.path.insert(0,'/home/dev/data') reload(sys) #加不加都起作用
添加再sys.path最后面
import sys sys.path.append('/home/dev/data2')
'__main__' is not a package
https://blog.csdn.net/nuaa_llf/article/details/89883293
经过一番百度,在Stack Overflow中找到了答案——相对导入只有在父模块已经在当前运行环境中被导入过才有用。
对于这一问题,官方文档intra-package-references也给出了解释:Note that relative imports are based on the name of the current module. Since the name of the main module is always “main”, modules intended for use as the main module of a Python application must always use absolute imports.
这里揭示了报错的缘由,相对导入基于当前模块的名称,因为主模块总被命名为
"__main__"
。当我们从主模块启动时,Python就识图用"__main__"
替换"."
,于是那句话实际便成了from __main__.Wheel import Wheel
,这当然是找不到的。
Package Relative Imports
https://docs.python.org/3/reference/import.html#package-relative-imports
包内部的相对寻址方法,前提是包必须先加载。
Relative imports use leading dots. A single leading dot indicates a relative import, starting with the current package. Two or more leading dots indicate a relative import to the parent(s) of the current package, one level per dot after the first. For example, given the following package layout:
package/ __init__.py subpackage1/ __init__.py moduleX.py moduleY.py subpackage2/ __init__.py moduleZ.py moduleA.py
In either
subpackage1/moduleX.py
orsubpackage1/__init__.py
, the following are valid relative imports:from .moduleY import spam from .moduleY import spam as ham from . import moduleY from ..subpackage1 import moduleY from ..subpackage2.moduleZ import eggs from ..moduleA import foo
Absolute imports may use either the
import <>
orfrom <> import <>
syntax, but relative imports may only use the second form; the reason for this is that:import XXX.YYY.ZZZ
should expose
XXX.YYY.ZZZ
as a usable expression, but .moduleY is not a valid expression.
ModuleNotFoundError with pytest
https://stackoverflow.com/questions/54895002/modulenotfounderror-with-pytest
3I want my tests folder separate to my application code. My project structure is like so
myproject/ myproject/ myproject.py moduleone.py tests/ myproject_test.py
myproject.py
from moduleone import ModuleOne class MyProject(object) ....
myproject_test.py
from myproject.myproject import MyProject import pytest ...
I use
myproject.myproject
since I use the commandpython -m pytest
from the project root directory
./myproject/
However, then the imports within those modules fail with
E ModuleNotFoundError: No module named 'moduleone'
solution
Be sure to include
.
dot in the$PYTHONPATH
env var.You can use this code fragment to debug such issues:
import pprint import sys pprint.pprint(sys.path)
Your question managed to use
myproject
at three different levels. At least during debugging you might want to use three distinct names, to reduce possible confusion.
good practice
Good practice: use a Makefile or some other automation tool
If you are lazy and do not want to type that long command all the time, one option is to create a
Makefile
in your project's root dir with, e.g., the following:.PHONY: install test default: test install: pip install --upgrade . test: PYTHONPATH=. pytest
Which allows you to simply run:
make test
or (even shorter)
make