小伙伴们,你们有遇到过调用自己写的模块(跨目录模块调用),提示你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())

运行结果

运行成功.png

到此,问题已经解决。

我们使用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 跨目录模块调用,你真的懂了吗?的更多相关文章

  1. Python3模块调用你真的会吗?不懂就来看一看?

    前言 学习Python自动化框架的时候,各种文件会相互之间的调用.刚学的时候是不是很头疼!有木有!!一步步告诉你如何调用文件里的类和方法. 经常会调用同目录下的文件还有跨文件的调用 调用同目录下文件A ...

  2. Python多层目录模块调用

    一. 引用模块在 父+级目录中: 1. 将导入模块所在目录(../model/模块)添加到系统环境变量path下,可添加多个 import syssys.path.append("../mo ...

  3. PHP中cookies跨目录无法调用

    <?php  setcookie("messagetime",time(),time()+60);  ?> 写法无法跨目录调用呢.在搜索引擎中搜索,并没有找到答案(可能 ...

  4. PHP中cookies跨目录无法调用解决办法

    localhost/a/test.php 中写入: <?php setcookie("user","zhangsan",time()+3600); ?&g ...

  5. Selenium 2自动化测试实战5(模块调用)

    一.模块调用 1.创建一个目录project,并且在目录下面创建两个文件 project/ 一 pub.py L一 count.py 在pub.py文件中创建add函数. #pub.py def ad ...

  6. pycharm跨目录调用文件

    笔者今天在一个测试qq群中遇到解决跨目录中调用文件的问题.现在来详细说一下. 以下图目录为例: 1.同目录下直接调用掉用.test2.py和test3.py在同一个目录test2下. 所以在test3 ...

  7. Python3基础(4)匿名函数、装饰器、生成器、迭代器、内置函数、json&pickle序列化、软件目录开发规范、不同目录间模块调用

    ---------------个人学习笔记--------------- ----------------本文作者吴疆-------------- ------点击此处链接至博客园原文------ 1 ...

  8. 1. python跨目录调用模块

    快速镜像安装第三方库 :  pip install -i https://pypi.tuna.tsinghua.edu.cn/simple numpy (三方库名字) 同目录下,我们可以直接调用模块, ...

  9. python 一些程序规范(跨目录调用文件)

    文档内容学习于 http://www.cnblogs.com/xiaozhiqi/ 参考: https://www.cnblogs.com/monologuesmw/p/9490093.html 软件 ...

随机推荐

  1. 如何找到linux centos7 中 redis.conf

    我们假设redis正在运行,但是我们找不带redis的配置文件redis.conf. 正确的示范: (1)systemctl status redis ● redis.service - LSB: s ...

  2. 基于Spring Boot的可直接运行的分布式ID生成器的实现以及SnowFlake算法详解

    背景 最近对snowflake比较感兴趣,就看了一些分布式唯一ID生成器(发号器)的开源项目的源码,例如百度的uid-generator,美团的leaf.大致看了一遍后感觉uid-generator代 ...

  3. Extjs editor 设置默认值

    一.前言 Ext js 给 editor 设置默认值用 value 无效,在 Model 中添加 defaultValue 即可. 二.实例 view: Ext.define('xxxx.view.P ...

  4. zabbix 批量添加web场景监控

    公司有大量测试环境的url需要监控是否能够访问,即url状态不为200即报警.状态为200即正常.因url比较多,且经常发生改变,如通过web场景配置(我没配过)会比较繁琐,工作量比较大.通过网上查找 ...

  5. bs4解析

    介绍:将一个html文档转换成BeautifulSoup对象,然后通过对象的方法或属性查找指定的节点内容 转换本地文件: ​ soup = BeautifulSoup(fp,'lxml') fp为文档 ...

  6. 在VMware Workstation10下CentOS7虚拟机中创建与主机共享文件夹的详细步骤

    一.前言 在使用虚拟机时,常常需要与宿主计算机(以下简称为主机)操作系统交换文件,为此需要在虚拟机与主机之间建立共享文件夹. 二. 安装VMTools 要使用共享文件机制,必须首先安装VMTools. ...

  7. 初始STM32

    主要内容: 1.什么是STM32 STM32有什么 STM32怎么选型号 一:什么是STM32 ST— 意法半寻体,是一个公司名,即SOC厂商(ARM是IP厂商,STM32中内核由ARM设计,外设例如 ...

  8. Form key length limit 2048 exceeded ,提交数据时,数据的键过长 或者是上传文件过大

    在ASP.NET Core MVC中,文件的key 默认最大为2048,文件上传的最大上传文件默认为20MB,如果我们想上传一些比较大的文件,就不知道怎么去设置了,没有了Web.Config我们应该如 ...

  9. MSSql-SP_who分析数据库性能

    https://blog.csdn.net/xiaoxu0123/article/details/5757640 https://www.cnblogs.com/kelelipeng/p/104959 ...

  10. 动手实现CNN卷积神经网络

    数据集采用的是手写数据集(http://yann.lecun.com/exdb/mnist/): 本文构建的CNN网络图如下: 像素点:28*28 = 784,55000张手写数字图片. # -*- ...