原文链接:http://blog.csdn.net/lis_12/article/details/52883729

问题1

同一个目录下,有两个Python文件,A.py,B.py

#A.py
from B import D
class C(object):
pass #B.py
from A import C
class D(object):
pass
'''
执行A.py
结果:
Traceback (most recent call last):
File "A.py", line 4, in <module>
from B import D
File "B.py", line 4, in <module>
from A import C
File "A.py", line 4, in <module>
from B import D
ImportError: cannot import name D
'''

why?

from B import D的执行机制

可以利用sys.modules查看是否包含B模块,如查看os模块,输入

>>> sys.modules[‘os’].

  1. 存在模块B

    如果sys.modules有B这个键,就会获取相对应的值,也就是modules对象,然后从模块B的__dict__列表中查找并获取名称为D的对象,如果不存在,抛出异常.

    模块B的__dict__列表可利用dir(B)来查看.

  2. 不存在模块B

    如果不存在B这个键的话,则会为B创建一个模块对象,此时模块对象的__dict__列表为空,然后在搜索路径下查找并执行B.py,以填充模块B对象的__dict__列表,然后从__dict__列表中查找名称为D的对象,如果找不到,则抛出异常.

    注:module ,模块的意思

根据上面修改代码,查看sys.modules变化情况

#A.py
#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys
try:
print 'module B: %s'%sys.modules['B']
except Exception,e:
print u'没有module B %s'%e try:
print 'module A: %s'%sys.modules['A']
except Exception,e:
print u'没有module A %s'%e from B import D
class C(object):
pass #B.py
from A import C
class D(object):
pass
'''
执行A.py
结果:
没有module B 'B'
没有module A 'A'
module B: <module 'B' from 'B.pyc'>
module A: <module 'A' from 'A.py'>
Traceback (most recent call last):
File "A.py", line 4, in <module>
from B import D
File "B.py", line 4, in <module>
from A import C
File "A.py", line 4, in <module>
from B import D
ImportError: cannot import name D

问题1答案

  1. 运行A.py,当执行到from B import D语句时,因为还没有运行过B.py,所以sys.modules中没有B这个键.会创建一个键B并赋值为模块B对象,只不过此时模块B对象是空的,里面什么都没有;
  2. 然后,暂停执行A.py的其他语句,Python 在搜索路径下查找B.py,找到同目录下的B.py并运行,为了填充模块B对象中的__dict__列表.当执行到from A import C时,也会检查sys.modules中是否有名为A的模块,但因为A.py还没有读取完,所以并没有在sys.modules中缓存对应的信息.同样,Python 会创建一个键A并赋值为空的模块A对象.暂停执行B.py并寻找、从头执行A.py.
  3. 这时,会再次执行到from B import D语句,由于在第一步时已经在sys.modules创建了键B的模块B对象,所以直接获取到,但此时模块B对象中的__dict__列表还是空的,里面什么都没有啊,所以找不到名为D的对象,抛出异常.

对照运行结果,是不是很符合- -!

(表述能力有限,多看代码吧- -)

问题2 将上述from import 换成 import

#A1.py
#!/usr/bin/python
# -*- coding: utf-8 -*-
import sys
try:
print 'module B1: %s'%sys.modules['B1']
except Exception,e:
print u'没有module B1 %s'%e try:
print 'module A1: %s'%sys.modules['A1']
except Exception,e:
print u'没有module A1 %s'%e import B1 class C(object):
pass
try:
B1.D()
except Exception,e:
print u'B中没有属性D',e #B1.py
import A1
class D(object):
pass '''
执行A.py
结果:
没有module B1 'B1'
没有module A1 'A1'
module B1: <module 'B1' from 'B1.pyc'>
module A1: <module 'A1' from 'A1.py'>
B中没有属性D 'module' object has no attribute 'D'
'''

由程序结果可知,将from…import…改成import后,程序不会出错了,但是调用B1.D()时为什么会抛出异常呢?

问题2答案

  1. 运行A1.py,当执行到import B1语句时,因为还没有运行过B1.py,所以sys.modules中没有B1这个键.会创建一个键B1并赋值为模块B1对象,只不过此时这个模块对象是空的,里面什么都没有;

  2. 然后,暂停执行A1.py的其他语句,Python 在搜索路径下查找B1.py,找到同目录下的B1.py并运行,为了填充模块B1对象中的__dict__列表.当执行到import A1时,也会检查sys.modules中是否有名为A1的模块,但因为A1.py还没有读取完,所以并没有在sys.modules中缓存对应的信息.然后,同样的,Python 会创建一个键A1并赋值为空的模块A1对象.暂停执行B1.py并寻找、从头执行A1.py.

  3. 这时,会再次执行到import B1语句,由于在第一步时已经在sys.modules创建了模块B1对象,模块B1对象已经存在了,不需要执行B1.py,所以继续执行A1.py中的其他内容.

    注意:此时模块B1仍为空的,里面什么都没有.

  4. 当执行到B1.D()时,由于在模块B1对象的__dict__列表找不到名为D的对象,抛出异常.

问题3 修改问题1中的程序使的能正确运行

#A2.py
from B2 import D
class C(object):
pass #B2.py
class D(object):
pass
from A2 import C

简单说明:

A2.py->B2.py->A2.py时,D属性已经在B2的__dict__列表中了,所以不会报错…虽然这样写不会报错,但是强烈不推荐这么写….

总结

当Python程序导入其他模块时,要避免循环导入,不然总会出意向不到的问题….

注:循环导入,即A文件导入了B,B文件又导入了A.

重新导入模块
如果更新了一个已经用import语句导入的模块,内建函数reload()可以重新导入并运行更新后的模块代码.它需要一个模块对象做为参数.例如: 
import foo
... some code ...
reload(foo)          # 重新导入 foo

在reload()运行之后的针对模块的操作都会使用新导入代码,不过reload()并不会更新使用旧模块创建的对象,因此有可能出现新旧版本对象共存的情况。*注意* 使用C或C++编译的模块不能通过 reload() 函数来重新导入。记住一个原则,除非是在调试和开发过程中,否则不要使用reload()函数

python之from 和import执行过程分析的更多相关文章

  1. python:Attempted relative import in non-package

    problem:Attempted relative import in non-package 所谓相对路径其实就是相对于当前module的路径,但如果直接执行脚本,这个module的name就是“ ...

  2. Ansible系列(七):执行过程分析、异步模式和速度优化

    本文目录:1.1 ansible执行过程分析1.2 ansible并发和异步1.3 ansible的-t选项妙用1.4 优化ansible速度 1.4.1 设置ansible开启ssh长连接 1.4. ...

  3. python笔记-1(import导入、time/datetime/random/os/sys模块)

    python笔记-6(import导入.time/datetime/random/os/sys模块)   一.了解模块导入的基本知识 此部分此处不展开细说import导入,仅写几个点目前的认知即可.其 ...

  4. windows环境下把Python代码打包成独立执行的exe

    windows环境下把Python代码打包成独立执行的exe可执行文件   有时候因为出差,突然急需处理一批数据.虽然写好的脚本存储在云端随用随取,然而编译的环境还需要重新搭建,模块也需要重新装载,从 ...

  5. Python进阶(八)----模块,import , from import 和 `__name__`的使用

    Python进阶(八)----模块,import , from import 和 __name__的使用 一丶模块的初识 #### 什么是模块: # 模块就是一个py文件(这个模块存放很多相似的功能, ...

  6. Python通过paramiko批量远程主机执行命令

    一.前言 在日常运维的过程中,经常需要登录主机去执行一些命令,有时候需要登录一批主机执行相同的命,手动登录执行的化效率太慢, 所以可以通过Python的paramiko模块批量执行,本篇文章基于pyt ...

  7. Python脚本实现在cmd执行相关命令

    通过Python脚本实现,在cmd命令执行文件的cp(复制).rm(删除).rename(重命名).move(文件移动).mkdir(创建目录) cmd执行命令格式:python xxx.py 用户名 ...

  8. Python脚本打包成exe执行文件

    需求 一个教辅目录结构检查工具,目录结构是[书籍]-[章节]-[题目|答案]-[*.jpg],后台有个异步处理的服务,需要强依赖这个目录结构. 书籍解析是单独的pipeline,日志对用户不可见,这里 ...

  9. ASP.NET MVC应用程序执行过程分析

    ASP.NET MVC应用程序执行过程分析 2009-08-14 17:57 朱先忠 朱先忠的博客 字号:T | T   ASP.NET MVC框架提供了支持Visual Studio的工程模板.本文 ...

随机推荐

  1. Access MongoDB Data with Entity Framework 6

    This article shows how to access MongoDB data using an Entity Framework code-first approach. Entity ...

  2. 浅谈Android选项卡(一)

    选项卡,这样UI设计在很多方面都存在,window,web,ios,Android. 选项卡的主要作用,不用多介绍,可以在有线的空间内,显示出更多内容,同时也是操作起来也很方便.

  3. [软件工程]项目选择与NABCD模型分析

    项目 内容 这个作业属于哪个课程 2019春季计算机学院软件工程(罗杰) 这个作业的要求在哪里 团队项目选择 这课程的目标是 以实践形式熟悉软件开发流程,团队开发,合作学习 本次作业对课程的帮助是 确 ...

  4. JAVA数据结构--快速排序

    快排概念 快速排序(英语:Quicksort),又称划分交换排序(partition-exchange sort),一种排序算法,最早由东尼·霍尔提出.在平均状况下,排序个项目要(大O符号)次比较.在 ...

  5. centos7安装串口终端kermit

    1. 将usb转串口连接到PC上.通过dmesg命令可以查看USB转串口是否被PC识别.显示 ……attachec to ttyUSB0即被识别. 2. 安装kermit.     [seif@cen ...

  6. 基于python实现GET和POST请求及token相关调用

    GET请求实例: #coding:utf- import requests parm={"}#封装登录参数 r=requests.get("http://space.test.co ...

  7. 《数据密集型应用系统设计》读书笔记-ch1可靠、可扩展与可维护的应用系统

    我们以Twitter为例,使用其2012年11月发布的数据.Twitter的两个典型业务操作是: - 发布tweet消息: 用户可以快速推送新消息到所有的关注者,平均大约4.6k request/se ...

  8. 《大数据日知录》读书笔记-ch3大数据常用的算法与数据结构

    布隆过滤器(bloom filter,BF): 二进制向量数据结构,时空效率很好,尤其是空间效率极高.作用:检测某个元素在某个巨量集合中存在. 构造: 查询: 不会发生漏判(false negativ ...

  9. Unity 动画 命名

    unity标准的动画命名格式是 ?模型名@动画名 如boss1@idle ,这样导入进来之后unity会自动给这个动画命名为idle而不是Take 001.

  10. 剑指offer等算法总结归类

    从数据结构分 一.链表: 3.题目描述:输入一个链表,从尾到头打印链表每个节点的值(递归) 思路:递归调用,调一次,加一次到list中 14.题目描述:输入一个链表,输出该链表中倒数第k个结点 两个指 ...