python包机制,Attempted relative import in non-package,ImportError: cannot import name 'xx' from '__main

问题引入

在写python脚本时,想将两个脚本共有的配置抽出来,形成配置文件,在运行脚本时读取配置文件。

脚本工具目录结构:

	programoperater
		__init__.py
		autorun_startprogram.py		——起服务脚本
		autorun_checkstart.py			——检查启动脚本
		programsetting.py				——抽取的配置文件

在脚本中通过相对路径import配置文件:

from . import programsetting

在服务器用自己安装的python3.7.3报错:
在这里插入图片描述
用服务器自带的python2.7.5执行报错:
在这里插入图片描述

问题分析,即python包机制

官方解释:Relative imports use a module’s name attribute to determine that module’s position in the package hierarchy.
即:python import package都是根据每个module的__name__来实现的。

通过“from . import programsettingg”,programsetting就获得了“programoperater.programe”的__name__属性。前提是该programoperater被python解释器识别成了一个package来处理(比如在programoperater的同级文件夹下的运行的run.py有import programoperater.programe之类的语句):

newfolder/
└─ programoperater
│		__init__.py
│		autorun_startprogram.py		——起服务脚本
│		autorun_checkstart.py			——检查启动脚本
│		programsetting.py				——抽取的配置文件
│
└─ run.py

造成我引包的问题来了:
被我直接运行的脚本,都会被视为top-level script。top-level script的__name__被自动设置成__main__。因此,如果我从programoperater文件夹内部直接运行autorun_checkstart.py这个脚本,那么它的__name__就被置成了__main__,python也不会把它当作一个package,其中的relative import的语句自然就无法起作用了。

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.

解决方式

  1. 更改目录结构:

     programoperater
     │ 	 	__init__.py
     │   	autorun_checkstart.py
     │    	autorun_startprograms.py
     │  
     └─settings
             __init__.py
             programsetting.py
    
  2. 引包方式修改:

from settings import programsetting
  1. 通过这样修改,可直接运行指定脚本autorun_checkstart.py

官网包机制解读:https://docs.python.org/zh-cn/3/tutorial/modules.html#packages

你可能感兴趣的:(Python,程序小工具,python从入门到精通)