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 Django连接MySQL数据库做增删改查
Nov 07 Python
Python实现批量把SVG格式转成png、pdf格式的代码分享
Aug 21 Python
python复制文件的方法实例详解
May 22 Python
Django框架下在视图中使用模版的方法
Jul 16 Python
Python使用PyCrypto实现AES加密功能示例
May 22 Python
python实现批量修改文件名代码
Sep 10 Python
numpy找出array中的最大值,最小值实例
Apr 03 Python
pandas数据集的端到端处理
Feb 18 Python
Python3.7 dataclass使用指南小结
Feb 22 Python
基于python实现的百度新歌榜、热歌榜下载器(附代码)
Aug 05 Python
安装python3.7编译器后如何正确安装opnecv的方法详解
Jun 16 Python
python playwright 自动等待和断言详解
Nov 27 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
PHP中计算字符串相似度的函数代码
2012/12/29 PHP
PHP删除目录及目录下所有文件的方法详解
2013/06/06 PHP
PHP伪静态Rewrite设置之APACHE篇
2014/07/30 PHP
php验证手机号码
2015/11/11 PHP
PHP如何使用Memcached
2016/04/05 PHP
Referer原理与图片防盗链实现方法详解
2019/07/03 PHP
利用NodeJS和PhantomJS抓取网站页面信息以及网站截图
2013/11/18 NodeJs
jquery复选框全选/取消示例
2013/12/30 Javascript
JS脚本defer的作用示例介绍
2014/01/02 Javascript
js实现带有介绍的Select列表菜单实例
2015/08/18 Javascript
javascript实现查找数组中最大值方法汇总
2016/02/13 Javascript
原生javascript+css3编写的3D魔方动画旋扭特效
2016/03/14 Javascript
jQuery实现放大镜效果实例代码
2016/03/17 Javascript
js判断手机浏览器操作系统和微信浏览器的方法
2016/04/30 Javascript
JS 对象(Object)和字符串(String)互转方法
2016/05/20 Javascript
JavaScript中关于for循环删除数组元素内容时出现的问题
2016/11/21 Javascript
JavaScript之Date_动力节点Java学院整理
2017/06/28 Javascript
Angular 2.0+ 的数据绑定的实现示例
2017/08/09 Javascript
vue实现消息的无缝滚动效果的示例代码
2017/12/05 Javascript
jquery ajaxfileuplod 上传文件 essyui laoding 效果【防止重复上传文件】
2018/05/26 jQuery
js实现按钮开关单机下拉菜单效果
2018/11/22 Javascript
Nodejs + Websocket 指定发送及群聊的实现
2020/01/09 NodeJs
[01:09:10]NB vs Liquid Supermajor小组赛 A组胜者组决赛 BO3 第一场 6.2
2018/06/04 DOTA
通过PHP与Python代码对比的语法差异详解
2019/07/10 Python
Python 可变类型和不可变类型及引用过程解析
2019/09/27 Python
一款CSS3实现多功能下拉菜单(带分享按)的教程
2014/11/05 HTML / CSS
html5 offlline 缓存使用示例
2013/06/24 HTML / CSS
How TDD works
2012/09/30 面试题
资料员岗位职责
2013/11/17 职场文书
安全生产中长期规划实施方案
2014/02/21 职场文书
公司合作协议书范本
2014/04/18 职场文书
餐饮服务食品安全责任书
2014/07/25 职场文书
人力资源职位说明书
2014/07/29 职场文书
预备党员入党感言
2015/08/01 职场文书
三好学生主要事迹怎么写
2015/11/03 职场文书
学会掌握自己命运的十条黄金法则:
2019/08/08 职场文书