python 全局变量的import机制介绍


Posted in Python onSeptember 07, 2017

先把有问题的代码晒一下:

python 全局变量的import机制介绍

IServer.py

from abc import ABCMeta, abstractmethod
print __name__

class IServer:
  def __init__(self):
    pass

  @abstractmethod
  def DoWithA(self):
    pass

  @abstractmethod
  def DoWithB(self):
    pass

IServer_A.py

import IServer
serverType ='1001'
print __name__
dir()
from CreatFactory import GLOBAL_class_dic
dir()
class IServer_A(IServer.IServer):
  def __init__(self):
    pass

  def DoWithA(self):
    print 'Server_A do with interface A'

  def DoWithB(self):
    print 'Server_A do with interface B'

global GLOBAL_class_dic

print 'the id of GLOBAL_class_dic in A is:',id(GLOBAL_class_dic)
GLOBAL_class_dic[serverType] = IServer_A
print 'GLOBAL_class_dic in a is:', GLOBAL_class_dic

IServer_B.py

import IServer
serverType ='1002'from CreatFactory import GLOBAL_class_dic
print __name__

class IServer_B(IServer.IServer):
  def __init__(self):
    pass

  def DoWithA(self):
    print 'Server_B do with interface A'

  def DoWithB(self):
    print 'Server_B do with interface B'

print 'the id of GLOBAL_class_dic in B is:',id(GLOBAL_class_dic)
GLOBAL_class_dic[serverType] = IServer_B
print 'GLOBAL_class_dic in b is:', GLOBAL_class_dic

CreatFactory.py

#coding:UTF-8
import os;
import sys;
import threading
from misc import *

global GLOBAL_class_dic

GLOBAL_class_dic ={1:1}
print 'GLOBAL_class_dic in define is:', GLOBAL_class_dic
print 'the id of GLOBAL_class_dic in define is:', id(GLOBAL_class_dic)

dir()

import IServer_A
import IServer_B


def CreateServer(serverType):
  global GLOBAL_class_dic
  print 'GLOBAL_class_dic in use is:', GLOBAL_class_dic
  print 'the id of GLOBAL_class_dic in USE is:', id(GLOBAL_class_dic)
  if GLOBAL_class_dic.has_key(serverType):
    return GLOBAL_class_dic[serverType]
  else:
    return 'no'

if __name__ == '__main__':
  pass
  # 接收到报文后,根据报文的内容,从db中获取到serverType,假设获取到的serverType=1001

  print 'main'
  print 'GLOBAL_class_dic in main A is:', GLOBAL_class_dic
  serverType = '1002'
  server = CreateServer(serverType)
  print 'GLOBAL_class_dic in main B is:', GLOBAL_class_dic
  print 'server :',server
  server.DoWithA(server())

代码内已经加了调试的部分信息, 运行CreatFactory.py。调用DoWithA失败,提示AttributeError: 'str' object has no attribute 'DoWithA'。运行结果如下:

D:\Python27\python.exe "D:/DesignMode/Server --00/CreatFactory.py"
GLOBAL_class_dic in define is: {1: 1}
the id of GLOBAL_class_dic in define is: 36230176
['GLOBAL_class_dic', 'Misc', '__builtins__', '__doc__', '__file__', '__name__', '__package__', 'binascii', 'inspect', 'minidom', 'os', 'struct', 'sys', 'threading']
IServer
IServer_A
['IServer', '__builtins__', '__doc__', '__file__', '__name__', '__package__', 'serverType']
GLOBAL_class_dic in define is: {1: 1}
the id of GLOBAL_class_dic in define is: 36230032
['GLOBAL_class_dic', 'Misc', '__builtins__', '__doc__', '__file__', '__name__', '__package__', 'binascii', 'inspect', 'minidom', 'os', 'struct', 'sys', 'threading']
['IServer', '__builtins__', '__doc__', '__file__', '__name__', '__package__', 'serverType']
['GLOBAL_class_dic', 'IServer', '__builtins__', '__doc__', '__file__', '__name__', '__package__', 'serverType']
IServer_B
the id of GLOBAL_class_dic in B is: 36230032
GLOBAL_class_dic in b is: {1: 1, '1002': <class IServer_B.IServer_B at 0x022C2ED8>}
['GLOBAL_class_dic', 'IServer', '__builtins__', '__doc__', '__file__', '__name__', '__package__', 'serverType']
the id of GLOBAL_class_dic in A is: 36230032
GLOBAL_class_dic in a is: {1: 1, '1002': <class IServer_B.IServer_B at 0x022C2ED8>, '1001': <class IServer_A.IServer_A at 0x02273420>}
main
GLOBAL_class_dic in main A is: {1: 1}
GLOBAL_class_dic in use is: {1: 1}
the id of GLOBAL_class_dic in USE is: 36230176
GLOBAL_class_dic in main B is: {1: 1}
server : no
Traceback (most recent call last):
 File "D:/DesignMode/Server --00/CreatFactory.py", line 38, in <module>
  server.DoWithA(server())
AttributeError: 'str' object has no attribute 'DoWithA'

Process finished with exit code 1

从运行的结果,可以看到:GLOBAL_class_dic 被定义了2次。有两个不同的id,第一次定义分配了一块内存,第二次不明原因的又重新分配了一块内存,然后服务的自动注册全部注册在这块内存中,等到main函数使用的使用,又使用的是第一次申请的内存,所以导致程序运行失败。那问题就来了,为什么会被重新又分配了一次?

之所以会被重新定义一次全局变量,是因为在执行CreatFactory.py时,最开始定义了全局变量,此时该命名空间可使用的函数和变量打印:['GLOBAL_class_dic', 'Misc', '__builtins__', '__doc__', '__file__', '__name__', '__package__', 'binascii', 'inspect', 'minidom', 'os', 'struct', 'sys', 'threading',然后在import IServer_A,在IServer_A.py中,import IServer后,在from CreatFactory import GLOBAL_class_dic打印出可使用的函数和变量时,['IServer', '__builtins__', '__doc__', '__file__', '__name__', '__package__', 'serverType'],就没有GLOBAL_class_dic,程序发现没有,就又重新声明了一遍。似乎问题原因已经找到了。

python在导入的时候,有2种场景,一种就是在文件前普通的import语句,还有一种就是特殊的场景:__main__模块是相对于Python的导入系统。在最开始运行CreatFactory.py文件时,__name__打印的值是__main__,而再子类再次导入时,会在当前命名空间查找是否已经导入__name__=CreatFactory,发现这个模块不存在,故此又导入了一遍,全局变量由此又被重新定义分配了内存,后期全局变量在子类业务的使用就都使用该值,而在main函数里,使用的又是当前的作用域内的第一次定义的全局变量。

Python 相关文章推荐
Python中itertools模块用法详解
Sep 25 Python
简单谈谈Python中函数的可变参数
Sep 02 Python
如何在Python函数执行前后增加额外的行为
Oct 20 Python
Python Paramiko模块的安装与使用详解
Nov 18 Python
pandas系列之DataFrame 行列数据筛选实例
Apr 12 Python
python实现从wind导入数据
Dec 03 Python
后端开发使用pycharm的技巧(推荐)
Mar 27 Python
Jupyter Notebook打开任意文件夹操作
Apr 14 Python
python实现五子棋程序
Apr 24 Python
500行python代码实现飞机大战
Apr 24 Python
JupyterNotebook 输出窗口的显示效果调整实现
Sep 22 Python
python matplotlib工具栏源码探析三之添加、删除自定义工具项的案例详解
Feb 25 Python
Python 多线程的实例详解
Sep 07 #Python
Python 闭包的使用方法
Sep 07 #Python
Python基于回溯法子集树模板解决选排问题示例
Sep 07 #Python
Python基于回溯法子集树模板解决全排列问题示例
Sep 07 #Python
python中利用await关键字如何等待Future对象完成详解
Sep 07 #Python
Python基于回溯法子集树模板解决m着色问题示例
Sep 07 #Python
python中利用Future对象异步返回结果示例代码
Sep 07 #Python
You might like
在IIS7.0下面配置PHP 5.3.2运行环境的方法
2010/04/13 PHP
php防攻击代码升级版
2010/12/29 PHP
PHP的范围解析操作符(::)的含义分析说明
2011/07/03 PHP
PHP面向对象的进阶学习(抽像类、接口、final、类常量)
2012/05/07 PHP
一个显示某段时间内每个月的方法 返回由这些月份组成的数组
2012/05/16 PHP
dvwa+xampp搭建显示乱码的问题及解决方案
2015/08/23 PHP
如何使用GDB调试PHP程序
2015/12/08 PHP
Zend Framework教程之Zend_Config_Xml用法分析
2016/03/23 PHP
Thinkphp5 微信公众号token验证不成功的原因及解决方法
2017/11/12 PHP
jquery复选框CHECKBOX全选、反选
2008/08/30 Javascript
js 字符串操作函数
2009/07/25 Javascript
jQuery1.3.2 升级到jQuery1.4.4需要修改的地方
2011/01/06 Javascript
jQuery 文本框得失焦点的简单实例
2014/02/19 Javascript
JS实现仿雅虎首页快捷登录入口及导航模块效果
2015/09/19 Javascript
jQuery mobile的header和footer在点击屏幕的时候消失的解决办法
2016/07/01 Javascript
Vue2.0使用过程常见的一些问题总结学习
2017/04/10 Javascript
微信小程序图片左右摆动效果详解
2019/07/13 Javascript
JSX在render函数中的应用详解
2019/09/04 Javascript
浅谈vue项目用到的mock数据接口的两种方式
2019/10/09 Javascript
vue实现百度语音合成的实例讲解
2019/10/14 Javascript
vue-amap根据地址回显地图并mark的操作
2020/11/03 Javascript
解决vue props传Array/Object类型值,子组件报错的情况
2020/11/07 Javascript
[01:38]DOTA2 2015国际邀请赛中国区预选赛 Showopen
2015/06/01 DOTA
Python探索之实现一个简单的HTTP服务器
2017/10/28 Python
python中的set实现不重复的排序原理
2018/01/24 Python
python如何获取当前文件夹下所有文件名详解
2019/01/25 Python
一篇文章彻底搞懂Python中可迭代(Iterable)、迭代器(Iterator)与生成器(Generator)的概念
2019/05/13 Python
Python split() 函数拆分字符串将字符串转化为列的方法
2019/07/16 Python
利用python计算时间差(返回天数)
2019/09/07 Python
利用Tensorboard绘制网络识别准确率和loss曲线实例
2020/02/15 Python
基于python图书馆管理系统设计实例详解
2020/08/05 Python
开业主持词
2014/03/21 职场文书
葬礼司仪主持词
2014/03/31 职场文书
2016高考寄语集锦
2015/12/04 职场文书
Python集合的基础操作
2021/11/01 Python
python解析照片拍摄时间进行图片整理
2022/07/23 Python