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实现html转ubb代码(html2ubb)
Jul 03 Python
python实现的守护进程(Daemon)用法实例
Jun 02 Python
Python的“二维”字典 (two-dimension dictionary)定义与实现方法
Apr 27 Python
Python字符串处理实现单词反转
Jun 14 Python
Python简单生成随机数的方法示例
Mar 31 Python
如何优雅地改进Django中的模板碎片缓存详解
Jul 04 Python
Python实现通过解析域名获取ip地址的方法分析
May 17 Python
详解Django配置优化方法
Nov 18 Python
Python动态强类型解释型语言原理解析
Mar 25 Python
Django中的AutoField字段使用
May 18 Python
浅析Python中字符串的intern机制
Oct 03 Python
解决pytorch 模型复制的一些问题
Mar 03 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
php懒人函数 自动添加数据
2011/06/28 PHP
PHP在线生成二维码代码(google api)
2013/06/03 PHP
浅析php变量作用域的一些问题
2013/08/08 PHP
如何让搜索引擎抓取AJAX内容解决方案
2014/08/25 PHP
基于ThinkPHP5.0实现图片上传插件
2017/09/25 PHP
支持汉转拼和拼音分词的PHP中文工具类ChineseUtil
2018/02/23 PHP
xtree.js 代码
2007/03/13 Javascript
百度留言本js 大家可以参考下
2009/10/13 Javascript
JavaScript 数组运用实现代码
2010/04/13 Javascript
js判断undefined类型,undefined,null, 的区别详细解析
2013/12/16 Javascript
Javascript自定义函数判断网站访问类型是PC还是移动终端
2014/01/10 Javascript
JS在可编辑的div中的光标位置插入内容的方法
2014/11/20 Javascript
教你使用javascript简单写一个页面模板引擎
2015/05/05 Javascript
基于jQuery实现Ajax验证用户名是否可用实例
2018/03/25 jQuery
Node.js应用设置安全的沙箱环境
2018/04/23 Javascript
JavaScript实现的拼图算法分析
2019/02/13 Javascript
微信小程序开发实现的选项卡(窗口顶部/底部TabBar)页面切换功能图文详解
2019/05/14 Javascript
Openlayers绘制聚合标注
2020/09/28 Javascript
[56:41]iG vs Winstrike 2018国际邀请赛小组赛BO2 第二场
2018/08/17 DOTA
使用Python中的cookielib模拟登录网站
2015/04/09 Python
对python mayavi三维绘图的实现详解
2019/01/08 Python
pytorch加载自定义网络权重的实现
2020/01/07 Python
python+selenium+chromedriver实现爬虫示例代码
2020/04/10 Python
Python限制内存和CPU使用量的方法(Unix系统适用)
2020/08/04 Python
在 Python 中使用 7zip 备份文件的操作
2020/12/11 Python
使用HTML5和CSS3制作一个模态框的示例
2018/03/07 HTML / CSS
中国最大的团购网站:聚划算
2016/09/21 全球购物
WoolOvers澳洲官方网站:英国针织服装公司
2018/05/13 全球购物
学期自我鉴定
2013/11/04 职场文书
公务员个人自我评价分享
2013/11/06 职场文书
大学系主任推荐信范文
2013/12/24 职场文书
教研活动总结
2014/04/28 职场文书
环境卫生标语
2015/08/03 职场文书
2016国庆节67周年红领巾广播稿
2015/12/18 职场文书
五年级作文之劳动作文
2019/11/12 职场文书
python通过opencv调用摄像头操作实例分析
2021/06/07 Python