[转]python3 跨目录模块调用,你真的懂了吗?
小伙伴们,你们有遇到过调用自己写的模块(跨目录模块调用),提示你ImportError:No module named ...
的情况,如果有,而且到现在还没有搞明白的,我想说,你今天看对文章了。
这篇文章主要是讲解怎么还原一个出错的场景,然后分析出错原因,一步一步的解决这个问题的思路。
项目结构
代码内容
- # model1/student.py
- def get_name():
- return "hting"
- # model1/new_student.py
- from student import get_name #注意这里的导入包的方式,会导致后面的异常
- def get_student_name():
- return get_name()
- # model2/animal.py
- def get_name():
- return "dog"
- # model2/new_animal.py
- from model2.animal import get_name #注意这里的导入包的方式,和model1中new_student.py模块中的导入方式有什么不一样
- def get_student_name():
- return get_name()
注意上面脚本导入包的方式,和model1中new_student.py模块中的导入方式有什么不一样
- # testModel/test.py 这里是运行入口
- from model1 import student
- from model1 import new_student
- from model2 import animal
- from model2 import new_animal
- if __name__ == "__main__":
- print(student.get_name())
- print(new_student.get_student_name())
- print(animal.get_name())
- print(new_animal.get_student_name())
执行代码报错

解释出错原因
查看刚才的报错信息,我们可以知道,我们在执行test.py这个文件的时候,找不到student这个对象,那么我们找到包含“from student import get_name”的这个文件“new_student.py”,执行这个文件,没有报错,所以,这样写是绝对没有问题的,那么为什么我们在外部对new_student.py这个模块调用的时候会报错?这里就要涉及到我们的python导包顺序了。
(1)第一步:查找执行文件所在目录
(2)第二步:查找执行文件所属的项目目录
(3)第三步:查找path环境配置的目录
根据我的实验,其实所谓的导包顺序都是根据path中配置顺序来的。我们做个实验,在test.py中将path变量打印出来,结果如下
['C:\\HOMETing\\ForPython\\testforpath\\testModel', # 执行文件的所在目录
'C:\\Python35\\lib\\site-packages\\django-2.0-py3.5.egg',
'C:\\Python35\\lib\\site-packages\\pytz-2017.2-py3.5.egg',
'C:\\HOMETing\\ForPython\\testforpath', # 执行文件所在项目的根目录
'C:\\Python35\\python35.zip',
'C:\\Python35\\DLLs',
'C:\\Python35\\lib',
'C:\\Python35',
'C:\\Python35\\lib\\site-packages']
结合我们这个问题,会执行这样的步骤
(1)查找执行文件的所在目录,没有student这个对象
(2)查找项目的根目录下,没有student这个对象
(3)查找path中的其他目录也是没有这个student对象的
(4)执行上面4个步骤之后都没有找到这个对象,所以报错
根据上面的分析,多少应该有了解决思路:就是将我们student所在的目录加入到path变量中。
解决这个问题
根据上面步骤的分析,我们尝试将model1这个包路径加入到path变量中,看是否解决了问题。
在代码中添加如下代码
- import sys
- sys.path.append("../model1")
test.py模块修改之后的代码
- # test.py
- import sys
- sys.path.append("../model1")
- # print(sys.path) # 打印出path,调试使用
- from model1 import student
- from model1 import new_student
- from model2 import animal
- from model2 import new_animal
- if __name__ == "__main__":
- print(student.get_name())
- print(new_student.get_student_name())
- print(animal.get_name())
- print(new_animal.get_student_name())
运行结果

到此,问题已经解决。
我们使用print(sys.path)
将path打印出来看一下
[
'C:\\HOMETing\\ForPython\\testforpath\\testModel',
'C:\\Python35\\lib\\site-packages\\django-2.0-py3.5.egg',
'C:\\Python35\\lib\\site-packages\\pytz-2017.2-py3.5.egg',
'C:\\HOMETing\\ForPython\\testforpath',
'C:\\Python35\\python35.zip',
'C:\\Python35\\DLLs',
'C:\\Python35\\lib',
'C:\\Python35',
'C:\\Python35\\lib\\site-packages',
'../model1' # 新加入的path
]
另外:我建议不要使用将相对变量的路径加入到path中,建议使用绝对变量。方法如下
- import sys
- import os
- sys.path.append(os.path.abspath("../model1"))
- # os.path.abspath(path)
- # 返回path规范化的绝对路径。
练习题
读完这篇文章,我相信小伙伴们肯定是有收获的,那么我们尝试着做一个简单的题来巩固一下。
为什么new_student.py中的导包方式不会引发异常呢?
作者:亭子青年
链接:https://www.jianshu.com/p/61ed747680e2
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。
[转]python3 跨目录模块调用,你真的懂了吗?的更多相关文章
- Python3模块调用你真的会吗?不懂就来看一看?
前言 学习Python自动化框架的时候,各种文件会相互之间的调用.刚学的时候是不是很头疼!有木有!!一步步告诉你如何调用文件里的类和方法. 经常会调用同目录下的文件还有跨文件的调用 调用同目录下文件A ...
- Python多层目录模块调用
一. 引用模块在 父+级目录中: 1. 将导入模块所在目录(../model/模块)添加到系统环境变量path下,可添加多个 import syssys.path.append("../mo ...
- PHP中cookies跨目录无法调用
<?php setcookie("messagetime",time(),time()+60); ?> 写法无法跨目录调用呢.在搜索引擎中搜索,并没有找到答案(可能 ...
- PHP中cookies跨目录无法调用解决办法
localhost/a/test.php 中写入: <?php setcookie("user","zhangsan",time()+3600); ?&g ...
- Selenium 2自动化测试实战5(模块调用)
一.模块调用 1.创建一个目录project,并且在目录下面创建两个文件 project/ 一 pub.py L一 count.py 在pub.py文件中创建add函数. #pub.py def ad ...
- pycharm跨目录调用文件
笔者今天在一个测试qq群中遇到解决跨目录中调用文件的问题.现在来详细说一下. 以下图目录为例: 1.同目录下直接调用掉用.test2.py和test3.py在同一个目录test2下. 所以在test3 ...
- Python3基础(4)匿名函数、装饰器、生成器、迭代器、内置函数、json&pickle序列化、软件目录开发规范、不同目录间模块调用
---------------个人学习笔记--------------- ----------------本文作者吴疆-------------- ------点击此处链接至博客园原文------ 1 ...
- 1. python跨目录调用模块
快速镜像安装第三方库 : pip install -i https://pypi.tuna.tsinghua.edu.cn/simple numpy (三方库名字) 同目录下,我们可以直接调用模块, ...
- python 一些程序规范(跨目录调用文件)
文档内容学习于 http://www.cnblogs.com/xiaozhiqi/ 参考: https://www.cnblogs.com/monologuesmw/p/9490093.html 软件 ...
随机推荐
- 【计算机视觉】Object Proposal之BING理解
发现: 本论文主要有两大亮点.第一个亮点是发现了在固定窗口的大小下,物体与背景的梯度模式有所不同.如图1所示.图1(a)中绿框代表背景,红框代表物体.如果把这些框都resize成固定大小,比如8X8, ...
- win7下exe文件设置为开机启动
如何将自己的exe程序设置为开机自启动 如何将自己的exe程序设置为开机自启动 将自己的exe程序设置为开机自启动话不多说,直接看 首先1:cmd—>regedit 其次找到下面的路径就可以:( ...
- linux系统中RAID5磁盘冗余阵列配置(5块磁盘)
RAID5:需要至少三块(含)硬盘,兼顾存储性能.数据安全和储存成本. 如图所示”parity”块中保存的是其他硬盘数据的奇偶校验信息(并非其他硬盘的数据),以数据的奇偶校验信息来保证数据的安全,RA ...
- FutureWarning: Passing (type, 1) or '1type' as a synonym of type is deprecated;
/Users/jerryqi/PycharmProjects/DeepLearning/venv/lib/python3.7/site-packages/tensorflow/python/frame ...
- MySQL(五)中的redo&undo&binlog
MySQL中有六种日志文件,分别是:重做日志(redo log).回滚日志(undo log).二进制日志(binlog).错误日志(errorlog).慢查询日志(slow query log).一 ...
- S3. Android 消息推送
[概要] 消息推送
- spring boot 2.x版本:java.lang.ClassNotFoundException: org.springframework.boot.bind.RelaxedDataBinder
标题 ##搭建spring boot 2.0.3版本 使用alibaba的druid数据库连接池,com.github.pagehelper的分页插件,启动项目报错. 错误提示:java.lang.C ...
- java积累的细节问题
一.将几个数字进行拼接,拼接成字符串 一定要将""放到几个数字之前,否则就会把数字相加之后的数转化成字符串 如你需要拼接年份,月份,和日 如果:2018+12+13+"& ...
- 一个好隐蔽的C/C++代码bug
来自:微博@ruanyf, 一本书上说,下面的 C 语言代码可能会产生无限循环.看了半天,才意识到 Bug 在哪里. 完美解答: 数组下标越界.数组a总共有10个值,a[0]~a[9].for循环里面 ...
- python学习-20 集合
集合set 1.由不同元素组成的集合,集合是一组无序排列的,集合中的元素必须是不可变的 -定义集合 第一种: jh = {1,2,3,4} print(type(jh),jh) 运行结果: <c ...