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的WEB框架Flask中使用多个配置文件的解决方法
Apr 18 Python
Python 创建子进程模块subprocess详解
Apr 08 Python
Django中几种重定向方法
Apr 28 Python
Python脚本实现12306火车票查询系统
Sep 30 Python
Python编程实现蚁群算法详解
Nov 13 Python
Python3基于sax解析xml操作示例
May 22 Python
mac下给python3安装requests库和scrapy库的实例
Jun 13 Python
Django 表单模型选择框如何使用分组
May 16 Python
一行Python代码制作动态二维码的实现
Sep 09 Python
python实现的登录与提交表单数据功能示例
Sep 25 Python
解决Python使用列表副本的问题
Dec 19 Python
PyCharm配置anaconda环境的步骤详解
Jul 31 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获取url的函数代码
2011/08/02 PHP
php实现屏蔽掉黑帽SEO的搜索关键字
2015/04/15 PHP
javascript 数组的方法集合
2008/06/05 Javascript
JavaScript 核心参考教程 内置对象
2009/10/13 Javascript
js 延迟加载 改变JS的位置加快网页加载速度
2012/12/11 Javascript
深入理解JavaScript系列(47):对象创建模式(上篇)
2015/03/04 Javascript
js实现两点之间画线的方法
2015/05/12 Javascript
JS弹出窗口插件zDialog简单用法示例
2016/06/12 Javascript
浅析vue数据绑定
2017/01/17 Javascript
浅谈node模块与npm包管理工具
2018/01/03 Javascript
旺旺在线客服代码 旺旺客服代码生成器
2018/01/09 Javascript
你可能不知道的前端算法之文字避让(inMap)
2018/01/12 Javascript
vue cli 全面解析
2018/02/28 Javascript
JQuery通过后台获取数据遍历到前台的方法
2018/08/13 jQuery
vue iview多张图片大图预览、缩放翻转
2019/07/13 Javascript
JS实现移动端在线签协议功能
2019/08/22 Javascript
Layui多选只有最后一个值的解决方法
2019/09/02 Javascript
Vue proxyTable配置多个接口地址,解决跨域的问题
2020/09/11 Javascript
Python设计模式之中介模式简单示例
2018/01/09 Python
利用Pandas读取文件路径或文件名称包含中文的csv文件方法
2018/07/04 Python
Python XlsxWriter模块Chart类用法实例分析
2019/03/11 Python
Python为何不能用可变对象作为默认参数的值
2019/07/01 Python
django中瀑布流写法实例代码
2019/10/14 Python
python实现图片转换成素描和漫画格式
2020/08/19 Python
Matplotlib配色之Colormap详解
2021/01/05 Python
浅谈HTML5 Web Worker的使用
2018/01/05 HTML / CSS
一级方程式赛车官方网上商店:F1 Store(支持中文)
2018/01/12 全球购物
DC Shoes澳大利亚官方网上商店:购买DC鞋子
2019/10/25 全球购物
铭万公司.net面试题笔试题
2014/07/20 面试题
关爱女孩行动实施方案
2014/03/13 职场文书
签约仪式策划方案
2014/06/02 职场文书
路政管理求职信
2014/06/18 职场文书
投资合作意向书范本
2015/05/08 职场文书
小学一年级数学教学反思
2016/02/16 职场文书
浅谈tf.train.Saver()与tf.train.import_meta_graph的要点
2021/05/26 Python
js 数组 fill() 填充方法
2021/11/02 Javascript