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聊天程序实例代码分享
Nov 18 Python
django开发post接口简单案例,获取参数值的方法
Dec 11 Python
Django-Model数据库操作(增删改查、连表结构)详解
Jul 17 Python
Django单元测试工具test client使用详解
Aug 02 Python
解决Django 在ForeignKey中出现 non-nullable field错误的问题
Aug 06 Python
python制作英语翻译小工具代码实例
Sep 09 Python
用Python写一个自动木马程序
Sep 17 Python
基于python3监控服务器状态进行邮件报警
Oct 19 Python
Python迭代器模块itertools使用原理解析
Dec 11 Python
django序列化serializers过程解析
Dec 14 Python
Alpine安装Python3依赖出现的问题及解决方法
Dec 25 Python
python实现简单石头剪刀布游戏
Oct 24 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+ajax 无刷新删除数据
2010/02/20 PHP
php is_file()和is_dir()用于遍历目录时用法注意事项
2010/03/02 PHP
PHP 创建文件(文件夹)以及目录操作代码
2010/03/04 PHP
thinkPHP5.0框架URL访问方法详解
2017/03/18 PHP
JavaScript 版本自动生成文章摘要
2008/07/23 Javascript
brook javascript框架介绍
2011/10/10 Javascript
node.js中的http.request.end方法使用说明
2014/12/10 Javascript
jQuery实现购物车数字加减效果
2015/03/14 Javascript
js+css实现文字散开重组动画特效代码分享
2015/08/21 Javascript
JavaScript中的ParseInt("08")和“09”返回0的原因分析及解决办法
2016/05/19 Javascript
Javascript之String对象详解
2016/06/08 Javascript
Javascript随机标签云代码实例
2016/06/21 Javascript
浅谈addEventListener和attachEvent的区别
2016/07/14 Javascript
Vue.js递归组件构建树形菜单
2017/12/24 Javascript
angular 实时监听input框value值的变化触发函数方法
2018/08/31 Javascript
javascript实现文本框标签验证的实例代码
2018/10/14 Javascript
JQuery Ajax如何实现注册检测用户名
2020/09/25 jQuery
Python根据区号生成手机号码的方法
2015/07/08 Python
使用sklearn之LabelEncoder将Label标准化的方法
2018/07/11 Python
Python匿名函数/排序函数/过滤函数/映射函数/递归/二分法
2019/06/05 Python
Django 全局的static和templates的使用详解
2019/07/19 Python
python 动态迁移solr数据过程解析
2019/09/04 Python
python线程安全及多进程多线程实现方法详解
2019/09/27 Python
Pytorch 使用不同版本的cuda的方法步骤
2020/04/02 Python
Python Selenium异常处理的实例分析
2021/02/28 Python
今天学到的CSS最新技术(与图片背景相关)
2012/12/24 HTML / CSS
一款利用纯css3实现的超炫3D表单的实例教程
2014/12/01 HTML / CSS
html5简单示例_动力节点Java学院整理
2017/07/07 HTML / CSS
为什么需要版本控制?
2013/08/08 面试题
留学生求职信
2014/06/03 职场文书
反四风个人对照检查材料思想汇报
2014/09/25 职场文书
毕业设计指导教师评语
2014/12/30 职场文书
思想政治表现评语
2015/01/04 职场文书
如何理解python接口自动化之logging日志模块
2021/06/15 Python
mongodb数据库迁移变更的解决方案
2021/09/04 MongoDB
vue3种table表格选项个数的控制方法
2022/04/14 Vue.js