Python重新加载模块的实现方法


Posted in Python onOctober 16, 2018

importlib 模块的作用

模块,是一个一个单独的py文件 包,里面包含多个模块(py文件)

动态导入模块,这样就不用写那么多的import代码, 典型的例子: 自动同步服务,每个网站都有一个py文件。主进程里收到同步任务,根据名称来动态导入对应的py文件,这样就不用写那么多的import代码。(有点类似java的工厂方法)

但是,importlib并不能解决我在线修改py源码,再不重启进程的情况下,使修改生效。 这种情况,可以使用reload()

reload方法

为防止两个模块互相导入的问题,Python默认所有的模块都只导入一次,如果需要重新导入模块, Python2.7可以直接用reload(),Python3可以用下面几种方法:

方法一:基本方法 from imp import reload reload(module)

方法二:按照套路,可以这样 import imp imp.reload(module)

方法三:看看imp.py,有发现,所以还可以这样 import importlib importlib.reload(module)

方法四:根据天理,当然也可以这样 from importlib import reload reload(module)

在多进程的 程序中,一个进程的reload是无法影响另一个进程的

例子:

# 在主进程中启动多进程
def begin():
  """ 启动多进程 """
  plist = []
  for i in xrange(Num_process):
    p = Process(target=pre_run)
    p.start()
    plist.append(p)
  # 此进程监听redis消息,收到消息,即执行reload方法
  p = Process(target=reload_spider)
  p.start()
  plist.append(p)
  for p in plist:
    p.join()
# 监听redis,执行reload方法
def reload_spider():
  """ 监听文件变化,自动reload """
  rconn = redis.Redis(host=settings.REDIS_HOST, port=settings.REDIS_PORT, db=settings.REDIS_DB, password=settings.REDIS_PW)
  while True:
    try:
      key = 'reload-spider'
      value = rconn.get(key)
      print value
      if value == '1':
        crawler_module = importlib.import_module('crawlers.%s' % 'temp'.lower())
        reload(crawler_module)
        crawlerClass = getattr(crawler_module, 'temp'.upper())
        print 'reload_spider 中的class: %s' % (crawlerClass.name)
      # rconn.delete(key)
    except Exception, e:
      pass
    time.sleep(3)

另一个进程打印py文件里面一个变量

crawler = get_crawler_from_factory(mq_service, message)
  print crawler.name

结果发现,一个进程中进行了reload,并不能改变另外一个进程中的变量。那么在同一个进程中呢...

同一进程中,多线程,任一线程进行了reload操作,其他线程均受影响

def pre_run():
  t = threading.Thread(target=reload_spider, name='LoopThread')
  t.start()
  # t.join()
 
  """ 在每个进程里面再使用多线程 """
  pool = ThreadPool(Num_Thread)
  # 初始化mq通道
  mq_service = RabbitMqService()
 
  def callback(ch, method, properties, body):
    # 消息确认
    mq_service.input_channel.basic_ack(delivery_tag=method.delivery_tag)
    # 获取当前线程的名字
    current_process_name = multiprocessing.current_process().name
    logger.debug('当前进程名称:%s - pid: %s' % (current_process_name, os.getpid()))
    logger.debug('进程 %s,收到消息: %s' % (current_process_name, body))
    # 收到任务消息,丢给线程池处理
    pool.apply_async(run, (properties, body, mq_service))
  # 开始监听入口通道
  mq_service.receive(callback)

reload_spider中监听redi中的消息,如果有reload标识,进行reload操作

def reload_spider():
  """ 监听文件变化,自动reload """
  rconn = redis.Redis(host=settings.REDIS_HOST, port=settings.REDIS_PORT, db=settings.REDIS_DB, password=settings.REDIS_PW)
  while True:
    try:
      key = 'reload-spider'
      value = rconn.get(key)
      print value
      if value == '1':
        crawler_module = importlib.import_module('crawlers.%s' % 'temp'.lower())
        reload(crawler_module)
        crawlerClass = getattr(crawler_module, 'temp'.upper())
        print 'reload_spider 中的class: %s' % (crawlerClass.name)
      # rconn.delete(key)
    except Exception, e:
      pass
    time.sleep(3)

经测试,其他线程中的引入的变量,也改变了。

当然,消息监听最好使用mq或者是redis阻塞队列

以上这篇Python重新加载模块的实现方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持三水点靠木。

Python 相关文章推荐
Python程序设计入门(3)数组的使用
Jun 16 Python
python里将list中元素依次向前移动一位
Sep 12 Python
跟老齐学Python之玩转字符串(2)更新篇
Sep 28 Python
Python实现将一个大文件按段落分隔为多个小文件的简单操作方法
Apr 17 Python
详解Numpy中的广播原则/机制
Sep 20 Python
使用Scrapy爬取动态数据
Oct 21 Python
python3实现高效的端口扫描
Aug 31 Python
python 对任意数据和曲线进行拟合并求出函数表达式的三种解决方案
Feb 18 Python
python绘制动态曲线教程
Feb 24 Python
Python抓包程序mitmproxy安装和使用过程图解
Mar 02 Python
什么是Python中的顺序表
Jun 02 Python
Python基本知识点总结
Apr 07 Python
django Serializer序列化使用方法详解
Oct 16 #Python
为什么str(float)在Python 3中比Python 2返回更多的数字
Oct 16 #Python
对python添加模块路径的三种方法总结
Oct 16 #Python
Python中的CSV文件使用"with"语句的方式详解
Oct 16 #Python
详解django的serializer序列化model几种方法
Oct 16 #Python
Python调用C++,通过Pybind11制作Python接口
Oct 16 #Python
Python之inspect模块实现获取加载模块路径的方法
Oct 16 #Python
You might like
如何通过Linux命令行使用和运行PHP脚本
2015/07/29 PHP
浅谈php中fopen不能创建中文文件名文件的问题
2017/02/06 PHP
JavaScript 给汉字排序实例代码
2008/06/28 Javascript
网页前台通过js非法字符过滤代码(骂人的话等等)
2010/05/26 Javascript
jQuery1.4.2与老版本json格式兼容的解决方法
2011/02/12 Javascript
js中点击空白区域时文本框与隐藏层的显示与影藏问题
2013/08/26 Javascript
js验证输入是否为手机号码或电话号码示例
2013/12/30 Javascript
Javascript Memoizer浅析
2014/10/16 Javascript
纯js代码制作的网页时钟特效【附实例】
2016/03/30 Javascript
js实现纯前端的图片预览
2016/04/27 Javascript
微信小程序 picker-view 组件详解及简单实例
2017/01/10 Javascript
手把手教你使用vue-cli脚手架(图文解析)
2017/11/08 Javascript
vue几个常用跨域处理方式介绍
2018/02/07 Javascript
JavaScript创建对象方法实例小结
2018/09/03 Javascript
Vue-Router的使用方法
2018/09/05 Javascript
mpvue微信小程序多列选择器用法之省份城市选择的实现
2019/03/07 Javascript
vscode 配置vue+vetur+eslint+prettier自动格式化功能
2020/03/23 Javascript
详解React的回调渲染模式
2020/09/10 Javascript
JavaScript实现网页下拉菜单效果
2020/11/20 Javascript
梳理一下vue中的生命周期
2020/12/30 Vue.js
[01:10:58]Spirit vs NB Supermajor小组赛 A组败者组决赛 BO3 第二场 6.2
2018/06/03 DOTA
[38:38]完美世界DOTA2联赛PWL S3 access vs Rebirth 第二场 12.17
2020/12/18 DOTA
python 简易计算器程序,代码就几行
2009/08/29 Python
从零学python系列之浅谈pickle模块封装和拆封数据对象的方法
2014/05/23 Python
python检测是文件还是目录的方法
2015/07/03 Python
Python使用OpenCV进行标定
2018/05/08 Python
python Django的web开发实例(入门)
2019/07/31 Python
Django密码存储策略分析
2020/01/09 Python
Boda Skins皮衣官网:奢侈皮夹克,全球配送
2016/12/15 全球购物
类的核心特性有哪些
2014/01/01 面试题
iostream与iostream.h的区别
2015/01/16 面试题
应聘自荐书
2013/10/08 职场文书
住宅质量保证书
2014/04/29 职场文书
贷款担保申请书
2014/05/20 职场文书
防灾减灾日活动总结
2014/08/26 职场文书
党员干部学习三严三实心得体会
2016/01/05 职场文书