Python新手如何理解循环加载模块

循环加载模块

假设你有两个文件,a.py和b.py,在这两个文件中互相加载对方,例如:

在a.py中:

import b
def f():
return b.x
print f()

在b.py中:

import a
x = 1
def g():
print a.f()

首先,我们试着加载a.py:

>>> import a
1

没有问题。也许让人吃惊,毕竟有个感觉应该是问题的循环加载在这儿。

事实上在Python中仅仅是表面上的出现循环加载并不是什么问题。如果一个模块以及被加载了,Python不会傻到再去重新加载一遍。但是,当每个模块都想要互相访问定义在对方里的函数或者变量时,问题就来了。

让我们再回到之前的例子,当我们加载a.py时,它再加载b.py不会有问题,因为在加载b.py时,它并不需要访问a.py的任何东西,而在b.py中唯一的引用就是调用a.f()。但是这个调用是在函数g()中完成的,并且a.py或者b.py中没有人调用g(),所以这会儿心情还是美丽的。

但是当我们试图加载b.py时(之前没有加载a.py),会发生什么呢:

>>> import b
Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
   File "b.py", line 1, in <module>
  import a
   File "a.py", line 6, in <module>
  print f()
   File "a.py", line 4, in f
  return b.x
AttributeError: 'module' object has no attribute 'x'

恭喜你,出错了。这里问题出在加载b.py的过程中,Python试图加载a.py,并且在a.py中需要调用到f(),而函数f()又要访问到b.x,但是这个时候b.x却还没有被定义。这就产生了AttributeError异常。

解决的方案可以做一点细微的改动。改一下b.py,使得它在g()里面加载a.py:

x = 1
def g():
  import a
# 只有当g()被调用的时候才加载
  print a.f()

这会儿当我们加载b.py的时候,一切安好:

>>> import b
>>> b.g()
1
# 第一次输出,因为模块a在最后调用了‘print f()'
1
# 第二次输出,这是我们调用g()

知识点扩充:

1、使用系统函数__import_()

stringmodule = __import__('string')

2、使用imp 模块

import imp
stringmodule = imp.load_module('string',*imp.find_module('string'))

3、使用exec

import_string = "import string as stringmodule"
exec import_string

到此这篇关于Python新手如何理解循环加载模块的文章就介绍到这了,更多相关Python循环加载模块详解内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Python新手如何理解循环加载模块

    循环加载模块 假设你有两个文件,a.py和b.py,在这两个文件中互相加载对方,例如: 在a.py中: import b def f(): return b.x print f() 在b.py中: import a x = 1 def g(): print a.f() 首先,我们试着加载a.py: >>> import a 1 没有问题.也许让人吃惊,毕竟有个感觉应该是问题的循环加载在这儿. 事实上在Python中仅仅是表面上的出现循环加载并不是什么问题.如果一个模块以及被加载了,Pyt

  • Python实现动态加载模块、类、函数的方法分析

    本文实例讲述了Python实现动态加载模块.类.函数的方法.分享给大家供大家参考,具体如下: 动态加载模块: 方式1:系统函数__import__() 方式2:imp, importlib 模块 方式3:exec 函数 动态加载类和函数 首先,使用加载模块,使用内置函数提供的反射方法getattr(),依次按照层级获取模块->类\全局方法->类对象\类方法. test_import_module.py class ClassA: def test(self): print('test') in

  • Python自动重新加载模块详解(autoreload module)

    守护进程模式 使用python开发后台服务程序的时候,每次修改代码之后都需要重启服务才能生效比较麻烦. 看了一下Python开源的Web框架(Django.Flask等)都有自己的自动加载模块功能(autoreload.py),都是通过subprocess模式创建子进程,主进程作为守护进程,子进程中一个线程负责检测文件是否发生变化,如果发生变化则退出,主进程检查子进程的退出码(exist code)如果与约定的退出码一致,则重新启动一个子进程继续工作. 自动重新加载模块代码如下: autorel

  • JavaScript 模块的循环加载实现方法

    "循环加载"(circular dependency)指的是,a脚本的执行依赖b脚本,而b脚本的执行又依赖a脚本. // a.js var b = require('b'); // b.js var a = require('a'); 通常,"循环加载"表示存在强耦合,如果处理不好,还可能导致递归加载,使得程序无法执行,因此应该避免出现. 但是实际上,这是很难避免的,尤其是依赖关系复杂的大项目,很容易出现a依赖b,b依赖c,c又依赖a这样的情况.这意味着,模块加载机

  • Python之inspect模块实现获取加载模块路径的方法

    该文主要介绍如何获取模块的路径,需要申明的是这里所说的模块可以是功能实现的该模块,也可以是别的模块. 使用到的是 inspect 模块的 .getsourcefile(需要获取的模块名) 创建test.py内容如下: import os import inspect class pathManager(object): def __init__(self): pass def _abPath(self): modulePath = inspect.getsourcefile(os) abPath

  • Python重新加载模块的实现方法

    importlib 模块的作用 模块,是一个一个单独的py文件 包,里面包含多个模块(py文件) 动态导入模块,这样就不用写那么多的import代码, 典型的例子: 自动同步服务,每个网站都有一个py文件.主进程里收到同步任务,根据名称来动态导入对应的py文件,这样就不用写那么多的import代码.(有点类似java的工厂方法) 但是,importlib并不能解决我在线修改py源码,再不重启进程的情况下,使修改生效. 这种情况,可以使用reload() reload方法 为防止两个模块互相导入的

  • 详解CommonJS和ES6模块循环加载处理的区别

    CommonJS模块规范使用require语句导入模块,module.exports导出模块,输出的是值的拷贝,模块导入的也是输出值的拷贝,也就是说,一旦输出这个值,这个值在模块内部的变化是监听不到的. ES6模块的规范是使用import语句导入模块,export语句导出模块,输出的是对值的引用.ES6模块的运行机制和CommonJS不一样,遇到模块加载命令import时不去执行这个模块,只会生成一个动态的只读引用,等真的需要用到这个值时,再到模块中取值,也就是说原始值变了,那输入值也会发生变化

  • Python如何重新加载模块

    问题 你想重新加载已经加载的模块,因为你对其源码进行了修改. 解决方案 使用imp.reload()来重新加载先前加载的模块.举个例子: >>> import spam >>> import imp >>> imp.reload(spam) <module 'spam' from './spam.py'> >>> 讨论 重新加载模块在开发和调试过程中常常很有用.但在生产环境中的代码使用会不安全,因为它并不总是像您期望的那样

  • Python实现从文件中加载数据的方法详解

    前几篇都是手动录入或随机函数产生的数据.实际有许多类型的文件,以及许多方法,用它们从文件中提取数据来图形化. 比如之前python基础(12)介绍打开文件的方式,可直接读取文件中的数据,扩大了我们的数据来源.下面,将展示几种方法. 我们将使用内置的 csv 模块加载CSV文件 CSV文件是一种特殊的文本文件,文件中的数据以逗号作为分隔符,很适合进行数据的解析.先用excle建立如下表格和数据,另存为csv格式文件,放到代码目录下. 包含在Python标准库中自带CSV 模块,我们只需要impor

  • node.js使用require()函数加载模块

    详细说明均以写在注释之中,这里就不啰嗦了,小伙伴们自己详细看吧,千万别吧注释当成空气了. 复制代码 代码如下: /*在node中,可以使用require()函数来加载模块.  * require函数使用一个参数,参数值可以带有完整路径的模块的文件名,也可以为模块名.当使用node中提供的模块时,在require函数中只需要指定模块名即可.  * */ //建立一个页面2.js;代码如下 var name="思思博士"; exports.name=name; //建立一个页面1.js;代

随机推荐