Module Search of Python

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 named spam.py in a list of directories given by the variable sys.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 variable PATH).

  • 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 or subpackage1/__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 <> or from <> 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

3
 

I 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 command

python -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
原文地址:https://www.cnblogs.com/lightsong/p/14062337.html