在Python中对于import语句导入模块的问题,肯定是十分简单的,但我们今天讲的重点是说一说Python中import导入
上一级目录模块
及
循环import的问题
import上一级目录的模块
在Python的语法中,“import module”会去用 sys.path 搜索,这里的sys.path是个列表,可以供我们去动态修改。
当我们要去导入某个目录下的模块时,需要用到sys.path.insert(0,somedir)来加入到搜索路径,这样才能实现模块的导入(import)。
但是,这样通过 import上一级目录的module,可以sys.path.insert(0,parentdir) 导入模块的方法,用到的路径是绝对路径,当主文件储存位置发生变动时,就无法成功导入。 这里就要提及到动态获取上一级目录的方法。
动态方法来获取上一级目录:
import os,sys
parentdir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.insert(0,parentdir)
小问答:
为什么用sys.path.insert(0,parentdir) 而不是用sys.path.append(parentdir)呢?
这里的遍历搜索路径,为了避免因存在同名模块而导致导入出错的问题。所以用sys.path.insert(0,parentdir)先确定指定的这个目录下去遍历模块。
解决循环import的问题
在Python中还有个常见的问题就是 循环import(即circular import)的问题。
常见的一种情况就是:
无线网卡安装的时候,却需要在网上下载网卡驱。。。
安装压缩软件的时候,从网上下载的压缩软件安装程序却是被压缩了的。。。
循环依赖就类似于这种情况。
举个栗子:
在models.py中,
from server import db
class User(db.Model):
pass
在server.py中,
from flask import Flask
from flask.ext.sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:tmp/test.db'
db = SQLAlchemy(app)
from models import User
这样就产生了循环import的问题。
解决循环import的3种主要方法。
1.延迟导入(lazy import)
将它限制为局部作用域中,就是把import语句写在方法或函数里面。
这种方法的缺点就是会有性能问题。
2.将 "from AAA import BBB" 改成 "import xxx;xxx.yyy" 的访问形式
3.组织代码
出现循环import的问题往往意味着代码的布局有问题,那我们就可以通过合并或者分离竞争资源的方式将循环变成单向。
# ①合并的话就是都写到一个文件里面去。
# ②分离的话就是把需要import的资源提取到一个第三方文件去。