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将文本转换成图片输出的方法
Apr 28 Python
Python使用matplotlib实现绘制自定义图形功能示例
Jan 18 Python
Python读取数据集并消除数据中的空行方法
Jul 12 Python
在IPython中执行Python程序文件的示例
Nov 01 Python
Python面向对象之类的内置attr属性示例
Dec 14 Python
Python类装饰器实现方法详解
Dec 21 Python
Python 保持登录状态进行接口测试的方法示例
Aug 06 Python
python爬虫-模拟微博登录功能
Sep 12 Python
python+OpenCV实现图像拼接
Mar 05 Python
python 实现两个npy档案合并
Jul 01 Python
使用Python爬虫爬取小红书完完整整的全过程
Jan 19 Python
python 使用tkinter与messagebox写界面和弹窗
Mar 20 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
WINDOWS服务器安装多套PHP的另类解决方案
2006/10/09 PHP
PHP 远程文件管理,可以给表格排序,遍历目录,时间排序
2009/08/07 PHP
写出高质量的PHP程序
2012/02/04 PHP
php实现保存submit内容之后禁止刷新
2014/03/19 PHP
php上传中文文件名乱码问题处理方案
2015/02/03 PHP
PHP通过加锁实现并发情况下抢码功能
2016/08/10 PHP
javascript里的条件判断
2007/02/27 Javascript
纯JS实现五子棋游戏兼容各浏览器(附源码)
2013/04/24 Javascript
zTree插件之单选下拉菜单实例代码
2013/11/07 Javascript
jquery 检测元素是否存在的实例代码
2013/11/19 Javascript
jquery让指定的元素闪烁显示的方法
2015/03/17 Javascript
逐一介绍Jquery data()、Jquery stop()、jquery delay()函数(详)
2015/11/04 Javascript
AngularJS 自定义过滤器详解及实例代码
2016/09/14 Javascript
ros::spin() 和 ros::spinOnce()函数的区别及详解
2016/10/01 Javascript
vue-cli项目中怎么使用mock数据
2017/09/27 Javascript
jQuery实现简单的下拉菜单导航功能示例
2017/12/07 jQuery
vue2.0模拟锚点的实例
2018/03/14 Javascript
js/jquery遍历对象和数组的方法分析【forEach,map与each方法】
2019/02/27 jQuery
javascript实现的图片预览和上传功能示例【兼容IE 9】
2020/05/01 Javascript
基于javascript处理二进制图片流过程详解
2020/06/08 Javascript
浅谈Python2.6和Python3.0中八进制数字表示的区别
2017/04/28 Python
Python 在字符串中加入变量的实例讲解
2018/05/02 Python
python模块和包的应用BASE_PATH使用解析
2019/12/14 Python
pymysql的简单封装代码实例
2020/01/08 Python
详解python中各种文件打开模式
2020/01/19 Python
python 判断txt每行内容中是否包含子串并重新写入保存的实例
2020/03/12 Python
特罗佩亚包官方网站:Tropea
2017/01/03 全球购物
澳大利亚婴儿礼品公司:The Baby Gift Company
2018/11/04 全球购物
Java面试中常遇到的问题,也是需要注意的几点
2013/08/30 面试题
教育英语专业毕业生的求职信
2014/03/13 职场文书
2014年督导工作总结
2014/11/19 职场文书
呼兰河传读书笔记
2015/06/30 职场文书
加强党性修养心得体会
2016/01/21 职场文书
python-opencv 中值滤波{cv2.medianBlur(src, ksize)}的用法
2021/06/05 Python
SpringAop日志找不到方法的处理
2021/06/21 Java/Android
tomcat默认最大连接数及相关调整方法
2022/05/06 Servers