python 导入问题的彻底解决

822 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

python import

sys.path存储了导入时可搜索的路径

ref

ModuleNotFoundError: No module named 'main.xxx'; 'main' is not a package问题

Python sys.path详细介绍

Python 3.x | 史上最详解的 导入(import)

导入规则

一些基础概念

  • pkg:包含__init__.py的目录,放了很多xx.py
  • module:xx.py文件
  • class、func、var等等

模块内置属性:

  • name 模块名字。 name == __main__时,直接运行本模块。
  • file 当前 module的绝对路径
  • dict
  • doc
  • package
  • path

搜索路径:

导入时,会从sys.path提供的路径中搜索要导入的东西

重要的是,sys.path会根据你执行python xxx.py和启动jupyter notebook的所在目录,把这个目录加到sys.path中。

  • 在工程根目录下启动jupyter notebook时,会自动添加..../project_root/srcsys.path

    • 在pycharm下直接启动jupyter notebook时,会添加运行的ipynb文件所在目录和工程根目录
  • 其他情况

  • 最好对于上一级或者上两级的目录直接sys.path.append([".."]),它接收list。

一些路径操作:

import sys,osos.path.abspath(__file__) #获取当前文件的全名
​
os.path.dirname() #获取当前对象的父级目录
​
os.chdir() #用于指定当工作目录
​
sys.path.insert()#将当前对象的路径添加到首位
​
sys.path.append() # 将当前环境变量添加到环境变量的末尾

可行方法:

src为根目录,从src的下一级目录开始导入,每次都是从src的下一级开始,即绝对导入

文件结构:
|---src
    |---Core
        |---__init__.py
        |---Wheel.py
        |---Parser.py
from Core.Wheel import Wheel

pycharm运行正常命令行运行报错

注意事项:

这样只能在pycharm中可以运行,在命令行中会报错:

ModuleNotFoundError: No module named 'practice'

原因:

观察pycharm的python console可以看到,在运行之前,pycharm添加了代码:

sys.path.extend(['/home/pbc/Documents/PycharmProjects/myEPI/src', ])

即,将工程根目录路径source root路径添加到了系统路径

经实验,src路径是有效的起作用的,根目录不起作用

解决方法:

src路径添加到系统路径

# sys.path.extend(['/home/pbc/Documents/PycharmProjects/myEPI', '/home/pbc/Documents/PycharmProjects/myEPI/src'])
# sys.path.extend(['/home/pbc/Documents/PycharmProjects/myEPI', ])
sys.path.extend(['/home/pbc/Documents/PycharmProjects/myEPI/src', ])

工作目录(wdir,cwd)

work directory

current work dorectory

当前所运行python文件所在的目录,

这个在CLI和pycharm中是一致的

import osprint(os.getcwd())

几种导入的常见使用

使用同目录下的module,做导入时:

  • 将目录变为包的形式(就是增加一个__init__.py文件)

  • __init__.py中导入所有module中建议给外部使用的

    from .xx_module import xx,xxx,...
    
  • 这样,在与同包同级的py文件中导入,可以直接跨过module,只要写:

    from xx_pkg import xx,xxx,...
    

主动添加src目录和工程根目录

import sys
import os
​
_current_path = os.path.dirname(__file__)
sys.path.extend([os.path.join(_current_path, "../../../myPro")])
sys.path.extend([os.path.join(_current_path, "../../src")])
print(sys.path)

\