ValueError: attempted relative import beyond top-level package
看这篇文章如果还不会。。。请顺着网线来打我!!!
镜像问题:
ModuleNotFoundError: No module named '__main__.xxxxx'; '__main__' is not a package
解决方法:
- 如果导入的模块和主程序在同个目录下,直接import就行了
- 如果导入的模块是在主程序所在目录的子目录下,可以在子目录中增加一个空白的__init__.py文件,该文件使得python解释器将子目录整个也当成一个模块,然后直接通过“import 子目录.模块”导入即可。
- 如果导入的模块是在主程序所在目录的父目录下,则要通过修改path来解决,有两种方法:
(1)通过”import sys,sys.path.append('父目录的路径')“来改变,这种方法属于一次性的,只对当前的python解释器进程有效,关掉python重启后就失效了。
(2)直接修改环境变量:在windows中是 “ set 变量=‘路径’ ” 例如:set PYTHONPATH=‘C:\test\...’ 查看是否设置成功用echo %PYTHONPATH%,而且进到python解释器中查看sys.path,会发现已经有了新增加的路径了。这 种方式是永久的,一次设置以后一直都有效。在linux中是 "export 变量=‘路径’ “,查看是" echo $变量 "
通过修改path是通用的方法,因为python解释器就是通过sys.path去一个地方一个地方的寻找模块的。
如果感觉很绕口你可以这样理解:
第一件事无视pycharm的导包提示,这地方pycharm真的坑。
(1)我们先解释报错原因
运行的入口程序脚本时,你的视野范围可能不是这个脚本的绝对路径作为出发点。怎么才能知道自己的视野的出发点呢??
再导入自定义包之前先用sys模块的sys.path查看自己的出发点:
它其实是一个列表的形式,我为了美观把它一个个打印出来了:
因为python加载路径是按sys.path顺序加载,所以依次
第一个出发点就是【C:\Users\WQBin\PycharmProjects\pyMibXgo\py_etl\history_table_etl】
所以他的..目录是
C:\Users\WQBin\PycharmProjects\pyMibXgo 发现没有,继续运行
第二个出发点就是【D:\app\PyCharm 2019.2.3\helpers\pydev】
所以他的..目录是
D:\app\PyCharm 2019.2.3\ 超出了包加载路径就会爆出attempted relative import beyond top-level package
所以尽量不要使用..这种操作,你不清楚,生产环境下sys.path的列表顺序。
那么为什么pycharm会有这样错误的提示呢?
那是因为他默认你的第一个视野出发点就是当前脚本的绝对路径,但事实上当前视野出发点列表顺序中的第一个并不是当前脚本的绝对路径。
所以使用..这种父目录的操作很容易越出python包加载范围
(2)解决方案
我们讲解一下第三个方法的第(1)个:
我的目的是把下面(如图)整个包丢在生产环境里直接运行
最好的方式就是直接让py_etl这个点作为整个视野第一个出发点(不是第一也行):
那么我们就要在我们导入包的之前sys.path的列表第中添加py_etl的路径【下图红色所示】。在导入py_etl下自定义包中无需展示相对路径直接引用即可
import sys
import os
sys.path.insert(0,os.path.dirname(os.getcwd()))
即使这里爆红这没啥事。
如果不会在生产环境使用,而是在pycharm中运行,你只是其次还有一个方法,直接把py_etl包设置为Sources Root
其实上面两个方法的【原理】都是相同的就是改变加载环境的路径,我们查看一下sys.path去佐证一下:
大多数人都以为是才智成就了科学家,他们错了,是品格。---爱因斯坦