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 import用法以及与from...import的区别
May 28 Python
Python数据类型详解(一)字符串
May 08 Python
老生常谈python之鸭子类和多态
Jun 13 Python
Python(TensorFlow框架)实现手写数字识别系统的方法
May 29 Python
python实现可变变量名方法详解
Jul 01 Python
python读写配置文件操作示例
Jul 03 Python
Python使用Pandas对csv文件进行数据处理的方法
Aug 01 Python
给 TensorFlow 变量进行赋值的方式
Feb 10 Python
使用Python实现批量ping操作方法
May 06 Python
PyQt5如何将.ui文件转换为.py文件的实例代码
May 26 Python
opencv-python的RGB与BGR互转方式
Jun 02 Python
PyQt 如何创建自定义QWidget
Mar 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获取ip的三个属性区别介绍(HTTP_X_FORWARDED_FOR,HTTP_VIA,REMOTE_ADDR)
2012/09/23 PHP
使用php实现下载生成某链接快捷方式的解决方法
2013/05/07 PHP
php插入排序法实现数组排序实例
2015/02/16 PHP
php计算两个整数的最大公约数常用算法小结
2015/03/05 PHP
thinkPHP显示不出验证码的原因与解决方法分析
2017/05/20 PHP
当前页禁止复制粘贴截屏代码小集
2013/07/24 Javascript
jQuery实现切换字体大小的方法
2015/03/10 Javascript
IE6兼容透明背景图片及解决方案
2015/08/19 Javascript
JS使用JSON作为参数实例分析
2016/06/23 Javascript
jQuery ztree实现动态树形多选菜单
2016/08/12 Javascript
第一次动手实现bootstrap table分页效果
2016/09/22 Javascript
Vue项目webpack打包部署到服务器的实例详解
2017/07/17 Javascript
angular中实现li或者某个元素点击变色的两种方法
2017/07/27 Javascript
JS实现简单短信验证码界面
2017/08/07 Javascript
JavaScript实现简单评论功能
2017/08/17 Javascript
js原生实现移动端手指滑动轮播图效果的示例
2018/01/02 Javascript
在Vue中使用highCharts绘制3d饼图的方法
2018/02/08 Javascript
webpack分离css单独打包的方法
2018/06/12 Javascript
简单了解JavaScript中的执行上下文和堆栈
2019/06/24 Javascript
Node.js实现简单管理系统
2019/09/23 Javascript
vue中使用GraphQL的实例代码
2019/11/04 Javascript
[36:37]2014 DOTA2华西杯精英邀请赛5 24 VG VS iG
2014/05/25 DOTA
Python和Perl绘制中国北京跑步地图的方法
2016/03/03 Python
Python之str操作方法(详解)
2017/06/19 Python
python脚本后台执行方式
2019/12/21 Python
python读取图像矩阵文件并转换为向量实例
2020/06/18 Python
Python 在局部变量域中执行代码
2020/08/07 Python
美国领先的精品家居照明和装饰产品在线零售商:LightsOnline.com
2018/01/23 全球购物
法人授权委托书
2014/04/03 职场文书
大学生社团活动总结
2014/04/26 职场文书
中学清明节活动总结
2014/07/04 职场文书
2015年七七事变78周年纪念活动方案
2015/05/06 职场文书
2016党员干部政治学习心得体会
2016/01/23 职场文书
2016年敬老月活动总结
2016/04/05 职场文书
golang json数组拼接的实例
2021/04/28 Golang
浅谈MySQL之select优化方案
2021/08/07 MySQL