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网络编程学习笔记(三):socket网络服务器
Jun 09 Python
使用Python的Django框架结合jQuery实现AJAX购物车页面
Apr 11 Python
ansible作为python模块库使用的方法实例
Jan 17 Python
python Socket之客户端和服务端握手详解
Sep 18 Python
python贪婪匹配以及多行匹配的实例讲解
Apr 19 Python
python获取文件路径、文件名、后缀名的实例
Apr 23 Python
Python中如何使用if语句处理列表实例代码
Feb 24 Python
Python面向对象之类的封装操作示例
Jun 08 Python
用python打印菱形的实操方法和代码
Jun 25 Python
用什么库写 Python 命令行程序(示例代码详解)
Feb 20 Python
Window系统下Python如何安装OpenCV库
Mar 05 Python
基于Django OneToOneField和ForeignKey的区别详解
Mar 30 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
Win2000+Apache+MySql+PHP4+PERL安装使用小结
2006/10/09 PHP
我的论坛源代码(九)
2006/10/09 PHP
PHP实现Soap通讯的方法
2014/11/03 PHP
Laravel中七个非常有用但很少人知道的Carbon方法
2017/09/21 PHP
php中关于换行的实例写法
2019/09/26 PHP
js 加载时自动调整图片大小
2008/05/28 Javascript
input 高级限制级用法
2009/03/26 Javascript
jQuery Validation实例代码 让验证变得如此容易
2010/10/18 Javascript
js根据日期判断星座的示例代码
2014/01/23 Javascript
bootstrap动态添加面包屑(breadcrumb)及其响应事件的方法
2017/05/25 Javascript
javascript回调函数的概念理解与用法分析
2017/05/27 Javascript
简单快速的实现js计算器功能
2017/08/17 Javascript
EasyUI创建人员树的实例代码
2017/09/15 Javascript
vue-cli 引入、配置axios的方法
2018/05/08 Javascript
mpvue构建小程序的方法(步骤+地址)
2018/05/22 Javascript
vue-router跳转时打开新页面的两种方法
2019/07/29 Javascript
js this 绑定机制深入详解
2020/04/30 Javascript
详解JavaScript中的数据类型,以及检测数据类型的方法
2020/09/17 Javascript
详解template标签用法(含vue中的用法总结)
2021/01/12 Vue.js
利用Tkinter和matplotlib两种方式画饼状图的实例
2017/11/06 Python
python 弹窗提示警告框MessageBox的实例
2019/06/18 Python
python中通过pip安装库文件时出现“EnvironmentError: [WinError 5] 拒绝访问”的问题及解决方案
2020/08/11 Python
如何实现一个python函数装饰器(Decorator)
2020/10/12 Python
日本非常有名的内衣丝袜品牌:GUNZE
2017/01/06 全球购物
当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递?
2014/09/09 面试题
保送生自荐信范文
2013/10/06 职场文书
给幼儿园老师的表扬信
2014/01/19 职场文书
初三学习决心书
2014/03/11 职场文书
员工入职担保书范文
2014/04/01 职场文书
入党推优材料
2014/06/02 职场文书
住房租房协议书
2014/08/20 职场文书
爱国主义教育演讲稿
2014/08/26 职场文书
上课随便讲话检讨书
2014/09/12 职场文书
党的群众路线教育实践活动整改方案
2014/10/28 职场文书
2015年度班主任自我评价
2015/03/11 职场文书
python爬虫之爬取笔趣阁小说
2021/04/22 Python