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 相关文章推荐
Python3实现从文件中读取指定行的方法
May 22 Python
Python中函数参数设置及使用的学习笔记
May 03 Python
Python 字符串大小写转换的简单实例
Jan 21 Python
Python向MySQL批量插数据的实例讲解
Mar 31 Python
Python minidom模块用法示例【DOM写入和解析XML】
Mar 25 Python
解决Django生产环境无法加载静态文件问题的解决
Apr 23 Python
Django基础知识 web框架的本质详解
Jul 18 Python
Python中PyQt5/PySide2的按钮控件使用实例
Aug 17 Python
python图形界面开发之wxPython树控件使用方法详解
Feb 24 Python
如何理解python中数字列表
May 29 Python
python自动统计zabbix系统监控覆盖率的示例代码
Apr 03 Python
python如何读取.mtx文件
Apr 22 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中替换换行符的几种方法小结
2012/10/15 PHP
Fedora下安装php Redis扩展笔记
2014/09/03 PHP
PHP中怎样防止SQL注入分析
2014/10/23 PHP
php中Array2xml类实现数组转化成XML实例
2014/12/08 PHP
使用XHGui来测试PHP性能的教程
2015/07/03 PHP
thinkPHP自动验证、自动添加及表单错误问题分析
2016/10/17 PHP
Yii 框架使用Forms操作详解
2020/05/18 PHP
extjs 列表框(multiselect)的动态添加列表项的方法
2009/07/31 Javascript
jquery实现图片翻页效果
2013/12/23 Javascript
JavaScript生成福利彩票双色球号码
2015/05/15 Javascript
javascript中SetInterval与setTimeout的定时器用法
2015/08/24 Javascript
浏览器兼容的JS写法总结
2016/04/27 Javascript
vue.js中指令Directives详解
2017/03/20 Javascript
vue.js指令v-model使用方法
2017/03/20 Javascript
原生JS实现不断变化的标签
2017/05/22 Javascript
vue组件传递对象中实现单向绑定的示例
2018/02/28 Javascript
vue+eslint+vscode配置教程
2019/08/09 Javascript
JavaScript中判断为整数的多种方式及保留两位小数的方法
2019/09/09 Javascript
基于Vue 撸一个指令实现拖拽功能
2019/10/09 Javascript
[58:32]EG vs Liquid 2018国际邀请赛小组赛BO2 第一场 8.18
2018/08/19 DOTA
详细探究Python中的字典容器
2015/04/14 Python
Selenium控制浏览器常见操作示例
2018/08/13 Python
python简单鼠标自动点击某区域的实例
2019/06/25 Python
python同步windows和linux文件
2019/08/29 Python
详解python程序中的多任务
2020/09/16 Python
使用phonegap进行本地存储的实现方法
2017/03/31 HTML / CSS
详解window.open被浏览器拦截的解决方案
2019/07/18 HTML / CSS
HTML5通过navigator.mediaDevices.getUserMedia调用手机摄像头问题
2020/04/27 HTML / CSS
亿阳信通股份有限公司C#笔试题
2016/12/06 面试题
小学国庆节活动方案策划书
2014/09/16 职场文书
党支部党的群众路线对照检查材料
2014/09/24 职场文书
农村党员学习党的群众路线教育实践活动心得体会
2014/11/04 职场文书
2014年客服工作总结范文
2014/11/13 职场文书
收入及婚姻状况证明
2014/11/20 职场文书
学校安全管理制度
2015/08/06 职场文书
Python OpenCV 彩色与灰度图像的转换实现
2021/06/05 Python