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中二维阵列的变换实例
Oct 09 Python
Python新手们容易犯的几个错误总结
Apr 01 Python
使用Python实现简单的服务器功能
Aug 25 Python
python numpy 显示图像阵列的实例
Jul 02 Python
详解django自定义中间件处理
Nov 21 Python
python 实现倒排索引的方法
Dec 25 Python
django 消息框架 message使用详解
Jul 22 Python
Python pip 安装与使用(安装、更新、删除)
Oct 06 Python
Anaconda+Pycharm环境下的PyTorch配置方法
Mar 13 Python
Django分组聚合查询实例分享
Apr 29 Python
如何使用scrapy中的ItemLoader提取数据
Sep 30 Python
Django限制API访问频率常用方法解析
Oct 12 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
redis查看连接数及php模拟并发创建redis连接的方法
2016/12/15 PHP
PHP实现将多个文件压缩成zip格式并下载到本地的方法示例
2018/05/23 PHP
php 实现银联商务H5支付的示例代码
2019/10/12 PHP
PHP安装扩展mcrypt以及相关依赖项深入讲解
2021/03/04 PHP
JavaScript 学习笔记一些小技巧
2010/03/28 Javascript
JS 实现完美include载入实现代码
2010/08/05 Javascript
jquery 单引号和双引号的区别及使用注意
2013/07/31 Javascript
将两个div左右并列显示并实现点击标题切换内容
2013/10/22 Javascript
用js代码和插件实现wordpress雪花飘落效果的四种方法
2014/12/15 Javascript
Backbone.js中的集合详解
2015/01/14 Javascript
JS实现表格数据各种搜索功能的方法
2015/03/03 Javascript
javaScript中Math()函数注意事项
2015/06/18 Javascript
文件上传,iframe跨域数据提交的实现
2016/11/18 Javascript
js实现可输入可选择的select下拉框
2016/12/21 Javascript
@ResponseBody 和 @RequestBody 注解的区别
2017/03/08 Javascript
AngularJS读取JSON及XML文件的方法示例
2017/05/25 Javascript
js图片放大镜实例讲解(必看篇)
2017/07/17 Javascript
jQuery 实现左右两侧菜单添加、移除功能
2018/01/02 jQuery
Node.js搭建WEB服务器的示例代码
2018/08/15 Javascript
如何在微信小程序里面退出小程序的方法
2019/04/28 Javascript
五分钟搞懂Vuex实用知识(小结)
2019/08/12 Javascript
layui在form表单页面通过Validform加入简单验证的方法
2019/09/06 Javascript
微信小程序 点击切换样式scroll-view实现代码实例
2019/10/11 Javascript
vue 获取到数据但却渲染不到页面上的解决方法
2020/11/19 Vue.js
[01:03]悬念揭晓 11月26日DOTA2完美盛典不见不散
2017/11/23 DOTA
python实现简单点对点(p2p)聊天
2017/09/13 Python
python DataFrame 修改列的顺序实例
2018/04/10 Python
python matplotlib库绘制条形图练习题
2019/08/10 Python
关于python pycharm中输出的内容不全的解决办法
2020/01/10 Python
python如何通过pyqt5实现进度条
2020/01/20 Python
HTML5 video 上传预览图片视频如何设置、预览视频某秒的海报帧
2018/08/28 HTML / CSS
幼儿园英语教学反思
2014/01/30 职场文书
党员四风问题对照检查材料
2014/09/27 职场文书
读《教育心理学》心得体会
2016/01/22 职场文书
MySQL子查询中order by不生效问题的解决方法
2021/08/02 MySQL
tomcat的catalina.out日志按自定义时间格式进行分割的操作方法
2022/04/02 Servers