File "collect_info.py", line 109, in <module>

回复

编程语言Not see︶ 回复了问题 • 1 人关注 • 2 个回复 • 43 次浏览 • 2 天前 • 来自相关话题

京东咚咚架构演进

开源技术koyo 发表了文章 • 0 个评论 • 74 次浏览 • 2016-08-24 22:26 • 来自相关话题

咚咚是什么?咚咚之于京东相当于旺旺之于淘宝,它们都是服务于买家和卖家的沟通。 自从京东开始为第三方卖家提供入驻平台服务后,咚咚也就随之诞生了。 我们首先看看它诞生之初是什么样的。
 

1.0 诞生(2010 - 2011)​

为了业务的快速上线,1.0 版本的技术架构实现是非常直接且简单粗暴的。 如何简单粗暴法?请看架构图,如下:




1.0 的功能十分简单,实现了一个 IM 的基本功能,接入、互通消息和状态。 另外还有客服功能,就是顾客接入咨询时的客服分配,按轮询方式把顾客分配给在线的客服接待。 用开源 Mina 框架实现了 TCP 的长连接接入,用 Tomcat Comet 机制实现了 HTTP 的长轮询服务。 而消息投递的实现是一端发送的消息临时存放在 Redis 中,另一端拉取的生产消费模型。

这个模型的做法导致需要以一种高频率的方式来轮询 Redis 遍历属于自己连接的关联会话消息。 这个模型很简单,简单包括多个层面的意思:理解起来简单;开发起来简单;部署起来也简单。 只需要一个 Tomcat 应用依赖一个共享的 Redis,简单的实现核心业务功能,并支持业务快速上线。

但这个简单的模型也有些严重的缺陷,主要是效率和扩展问题。 轮询的频率间隔大小基本决定了消息的延时,轮询越快延时越低,但轮询越快消耗也越高。 这个模型实际上是一个高功耗低效能的模型,因为不活跃的连接在那做高频率的无意义轮询。 高频有多高呢,基本在 100 ms 以内,你不能让轮询太慢,比如超过 2 秒轮一次,人就会在聊天过程中感受到明显的会话延迟。 随着在线人数增加,轮询的耗时也线性增长,因此这个模型导致了扩展能力和承载能力都不好,一定会随着在线人数的增长碰到性能瓶颈。

1.0 的时代背景正是京东技术平台从 .NET 向 Java 转型的年代,我也正是在这期间加入京东并参与了京东主站技术转型架构升级的过程。 之后开始接手了京东咚咚,并持续完善这个产品,进行了三次技术架构演进。
 

2.0 成长(2012)

我们刚接手时 1.0 已在线上运行并支持京东 POP(开放平台)业务,之后京东打算组建自营在线客服团队并落地在成都。 不管是自营还是 POP 客服咨询业务当时都起步不久,1.0 架构中的性能和效率缺陷问题还没有达到引爆的业务量级。 而自营客服当时还处于起步阶段,客服人数不足,服务能力不够,顾客咨询量远远超过客服的服务能力。 超出服务能力的顾客咨询,当时我们的系统统一返回提示客服繁忙,请稍后咨询。 这种状况导致高峰期大量顾客无论怎么刷新请求,都很可能无法接入客服,体验很差。 所以 2.0 重点放在了业务功能体验的提升上,如下图所示:




针对无法及时提供服务的顾客,可以排队或者留言。 针对纯文字沟通,提供了文件和图片等更丰富的表达方式。 另外支持了客服转接和快捷回复等方式来提升客服的接待效率。 总之,整个 2.0 就是围绕提升客服效率和用户体验。 而我们担心的效率问题在 2.0 高速发展业务的时期还没有出现,但业务量正在逐渐积累,我们知道它快要爆了。 到 2012 年末,度过双十一后开始了 3.0 的一次重大架构升级。
 

3.0 爆发(2013 - 2014)

经历了 2.0 时代一整年的业务高速发展,实际上代码规模膨胀的很快。 与代码一块膨胀的还有团队,从最初的 4 个人到近 30 人。 团队大了后,一个系统多人开发,开发人员层次不一,规范难统一,系统模块耦合重,改动沟通和依赖多,上线风险难以控制。 一个单独 tomcat 应用多实例部署模型终于走到头了,这个版本架构升级的主题就是服务化。

服务化的第一个问题如何把一个大的应用系统切分成子服务系统。 当时的背景是京东的部署还在半自动化年代,自动部署系统刚起步,子服务系统若按业务划分太细太多,部署工作量很大且难管理。 所以当时我们不是按业务功能分区服务的,而是按业务重要性级别划分了 0、1、2 三个级别不同的子业务服务系统。 另外就是独立了一组接入服务,针对不同渠道和通信方式的接入端,见下图。




更细化的应用服务和架构分层方式可见下图:




这次大的架构升级,主要考虑了三个方面:稳定性、效率和容量。 做了下面这些事情:
业务分级、核心、非核心业务隔离多机房部署,流量分流、容灾冗余、峰值应对冗余读库多源,失败自动转移写库主备,短暂有损服务容忍下的快速切换外部接口,失败转移或快速断路Redis 主备,失败转移大表迁移,MongoDB 取代 MySQL 存储消息记录改进消息投递模型
 
前 6 条基本属于考虑系统稳定性、可用性方面的改进升级。 这一块属于陆续迭代完成的,承载很多失败转移的配置和控制功能在上面图中是由管控中心提供的。 第 7 条主要是随着业务量的上升,单日消息量越来越大后,使用了 MongoDB 来单独存储量最大的聊天记录。 第 8 条是针对 1.0 版本消息轮询效率低的改进,改进后的投递方式如下图所示:




不再是轮询了,而是让终端每次建立连接后注册接入点位置,消息投递前定位连接所在接入点位置再推送过去。 这样投递效率就是恒定的了,而且很容易扩展,在线人数越多则连接数越多,只需要扩展接入点即可。 其实,这个模型依然还有些小问题,主要出在离线消息的处理上,可以先思考下,我们最后再讲。

3.0 经过了两年的迭代式升级,单纯从业务量上来说还可以继续支撑很长时间的增长。 但实际上到 2014 年底我们面对的不再是业务量的问题,而是业务模式的变化。 这直接导致了一个全新时代的到来。
 

4.0 涅槃(2015 至今 )

2014 年京东的组织架构发生了很大变化,从一个公司变成了一个集团,下设多个子公司。 原来的商城成为了其中一个子公司,新成立的子公司包括京东金融、京东智能、京东到家、拍拍、海外事业部等。 各自业务范围不同,业务模式也不同,但不管什么业务总是需要客服服务。 如何复用原来为商城量身订做的咚咚客服系统并支持其他子公司业务快速接入成为我们新的课题。

最早要求接入的是拍拍网,它是从腾讯收购的,所以是完全不同的账户和订单交易体系。 由于时间紧迫,我们把为商城订做的部分剥离,基于 3.0 架构对接拍拍又单独订做了一套,并独立部署,像下面这样。




虽然在业务要求的时间点前完成了上线,但这样做也带来了明显的问题:
复制工程,定制业务开发,多套源码维护成本高独立部署,至少双机房主备外加一个灰度集群,资源浪费大
 
以前我们都是面向业务去架构系统,如今新的业务变化形势下我们开始考虑面向平台去架构,在统一平台上跑多套业务,统一源码,统一部署,统一维护。 把业务服务继续拆分,剥离出最基础的 IM 服务,IM 通用服务,客服通用服务,而针对不同的业务特殊需求做最小化的定制服务开发。 部署方式则以平台形式部署,不同的业务方的服务跑在同一个平台上,但数据互相隔离。 服务继续被拆分的更微粒化,形成了一组服务矩阵(见下图)




而部署方式,只需要在双机房建立两套对等集群,并另外建一个较小的灰度发布集群即可,所有不同业务都运行在统一平台集群上,如下图:




更细粒度的服务意味着每个服务的开发更简单,代码量更小,依赖更少,隔离稳定性更高。 但更细粒度的服务也意味着更繁琐的运维监控管理,直到今年公司内部弹性私有云、缓存云、消息队列、部署、监控、日志等基础系统日趋完善, 使得实施这类细粒度划分的微服务架构成为可能,运维成本可控。 而从当初 1.0 的 1 种应用进程,到 3.0 的 6、7 种应用进程,再到 4.0 的 50+ 更细粒度的不同种应用进程。 每种进程再根据承载业务流量不同分配不同的实例数,真正的实例进程数会过千。 为了更好的监控和管理这些进程,为此专门定制了一套面向服务的运维管理系统,见下图:




统一服务运维提供了实用的内部工具和库来帮助开发更健壮的微服务。 包括中心配置管理,流量埋点监控,数据库和缓存访问,运行时隔离,如下图所示是一个运行隔离的图示:




细粒度的微服务做到了进程间隔离,严格的开发规范和工具库帮助实现了异步消息和异步 HTTP 来避免多个跨进程的同步长调用链。 进程内部通过切面方式引入了服务增强容器 Armor 来隔离线程, 并支持进程内的单独业务降级和同步转异步化执行。而所有这些工具和库服务都是为了两个目标:
让服务进程运行时状态可见让服务进程运行时状态可被管理和改变

最后我们回到前文留下的一个悬念,就是关于消息投递模型的缺陷。 一开始我们在接入层检测到终端连接断开后,消息无法投递,再将消息缓存下来,等终端重连接上来再拉取离线消息。 这个模型在移动时代表现的很不好,因为移动网络的不稳定性,导致经常断链后重连。 而准确的检测网络连接断开是依赖一个网络超时的,导致检测可能不准确,引发消息假投递成功。 新的模型如下图所示,它不再依赖准确的网络连接检测,投递前待确认消息 id 被缓存,而消息体被持久存储。 等到终端接收确认返回后,该消息才算投妥,未确认的消息 id 再重新登陆后或重连接后作为离线消息推送。 这个模型不会产生消息假投妥导致的丢失,但可能导致消息重复,只需由客户终端按消息 id 去重即可。




京东咚咚诞生之初正是京东技术转型到 Java 之时,经历这些年的发展,取得了很大的进步。 从草根走向专业,从弱小走向规模,从分散走向统一,从杂乱走向规范。 本文主要重心放在了几年来咚咚架构演进的过程,技术架构单独拿出来看我认为没有绝对的好与不好, 技术架构总是要放在彼时的背景下来看,要考虑业务的时效价值、团队的规模和能力、环境基础设施等等方面。 架构演进的生命周期适时匹配好业务的生命周期,才可能发挥最好的效果。
分享阅读原文:http://www.cnblogs.com/mindwind/p/5017591.html  查看全部
dongdong.png

咚咚是什么?咚咚之于京东相当于旺旺之于淘宝,它们都是服务于买家和卖家的沟通。 自从京东开始为第三方卖家提供入驻平台服务后,咚咚也就随之诞生了。 我们首先看看它诞生之初是什么样的。
 


1.0 诞生(2010 - 2011)​


为了业务的快速上线,1.0 版本的技术架构实现是非常直接且简单粗暴的。 如何简单粗暴法?请看架构图,如下:
Arch1.png

1.0 的功能十分简单,实现了一个 IM 的基本功能,接入、互通消息和状态。 另外还有客服功能,就是顾客接入咨询时的客服分配,按轮询方式把顾客分配给在线的客服接待。 用开源 Mina 框架实现了 TCP 的长连接接入,用 Tomcat Comet 机制实现了 HTTP 的长轮询服务。 而消息投递的实现是一端发送的消息临时存放在 Redis 中,另一端拉取的生产消费模型。

这个模型的做法导致需要以一种高频率的方式来轮询 Redis 遍历属于自己连接的关联会话消息。 这个模型很简单,简单包括多个层面的意思:理解起来简单;开发起来简单;部署起来也简单。 只需要一个 Tomcat 应用依赖一个共享的 Redis,简单的实现核心业务功能,并支持业务快速上线。

但这个简单的模型也有些严重的缺陷,主要是效率和扩展问题。 轮询的频率间隔大小基本决定了消息的延时,轮询越快延时越低,但轮询越快消耗也越高。 这个模型实际上是一个高功耗低效能的模型,因为不活跃的连接在那做高频率的无意义轮询。 高频有多高呢,基本在 100 ms 以内,你不能让轮询太慢,比如超过 2 秒轮一次,人就会在聊天过程中感受到明显的会话延迟。 随着在线人数增加,轮询的耗时也线性增长,因此这个模型导致了扩展能力和承载能力都不好,一定会随着在线人数的增长碰到性能瓶颈。

1.0 的时代背景正是京东技术平台从 .NET 向 Java 转型的年代,我也正是在这期间加入京东并参与了京东主站技术转型架构升级的过程。 之后开始接手了京东咚咚,并持续完善这个产品,进行了三次技术架构演进。
 


2.0 成长(2012)


我们刚接手时 1.0 已在线上运行并支持京东 POP(开放平台)业务,之后京东打算组建自营在线客服团队并落地在成都。 不管是自营还是 POP 客服咨询业务当时都起步不久,1.0 架构中的性能和效率缺陷问题还没有达到引爆的业务量级。 而自营客服当时还处于起步阶段,客服人数不足,服务能力不够,顾客咨询量远远超过客服的服务能力。 超出服务能力的顾客咨询,当时我们的系统统一返回提示客服繁忙,请稍后咨询。 这种状况导致高峰期大量顾客无论怎么刷新请求,都很可能无法接入客服,体验很差。 所以 2.0 重点放在了业务功能体验的提升上,如下图所示:
Arch2.png

针对无法及时提供服务的顾客,可以排队或者留言。 针对纯文字沟通,提供了文件和图片等更丰富的表达方式。 另外支持了客服转接和快捷回复等方式来提升客服的接待效率。 总之,整个 2.0 就是围绕提升客服效率和用户体验。 而我们担心的效率问题在 2.0 高速发展业务的时期还没有出现,但业务量正在逐渐积累,我们知道它快要爆了。 到 2012 年末,度过双十一后开始了 3.0 的一次重大架构升级。
 


3.0 爆发(2013 - 2014)


经历了 2.0 时代一整年的业务高速发展,实际上代码规模膨胀的很快。 与代码一块膨胀的还有团队,从最初的 4 个人到近 30 人。 团队大了后,一个系统多人开发,开发人员层次不一,规范难统一,系统模块耦合重,改动沟通和依赖多,上线风险难以控制。 一个单独 tomcat 应用多实例部署模型终于走到头了,这个版本架构升级的主题就是服务化。

服务化的第一个问题如何把一个大的应用系统切分成子服务系统。 当时的背景是京东的部署还在半自动化年代,自动部署系统刚起步,子服务系统若按业务划分太细太多,部署工作量很大且难管理。 所以当时我们不是按业务功能分区服务的,而是按业务重要性级别划分了 0、1、2 三个级别不同的子业务服务系统。 另外就是独立了一组接入服务,针对不同渠道和通信方式的接入端,见下图。
Arch3.png

更细化的应用服务和架构分层方式可见下图:
Arch4.png

这次大的架构升级,主要考虑了三个方面:稳定性、效率和容量。 做了下面这些事情:
  1. 业务分级、核心、非核心业务隔离
  2. 多机房部署,流量分流、容灾冗余、峰值应对冗余
  3. 读库多源,失败自动转移
  4. 写库主备,短暂有损服务容忍下的快速切换
  5. 外部接口,失败转移或快速断路
  6. Redis 主备,失败转移
  7. 大表迁移,MongoDB 取代 MySQL 存储消息记录
  8. 改进消息投递模型

 
前 6 条基本属于考虑系统稳定性、可用性方面的改进升级。 这一块属于陆续迭代完成的,承载很多失败转移的配置和控制功能在上面图中是由管控中心提供的。 第 7 条主要是随着业务量的上升,单日消息量越来越大后,使用了 MongoDB 来单独存储量最大的聊天记录。 第 8 条是针对 1.0 版本消息轮询效率低的改进,改进后的投递方式如下图所示:
Arch5.png

不再是轮询了,而是让终端每次建立连接后注册接入点位置,消息投递前定位连接所在接入点位置再推送过去。 这样投递效率就是恒定的了,而且很容易扩展,在线人数越多则连接数越多,只需要扩展接入点即可。 其实,这个模型依然还有些小问题,主要出在离线消息的处理上,可以先思考下,我们最后再讲。

3.0 经过了两年的迭代式升级,单纯从业务量上来说还可以继续支撑很长时间的增长。 但实际上到 2014 年底我们面对的不再是业务量的问题,而是业务模式的变化。 这直接导致了一个全新时代的到来。
 


4.0 涅槃(2015 至今 )


2014 年京东的组织架构发生了很大变化,从一个公司变成了一个集团,下设多个子公司。 原来的商城成为了其中一个子公司,新成立的子公司包括京东金融、京东智能、京东到家、拍拍、海外事业部等。 各自业务范围不同,业务模式也不同,但不管什么业务总是需要客服服务。 如何复用原来为商城量身订做的咚咚客服系统并支持其他子公司业务快速接入成为我们新的课题。

最早要求接入的是拍拍网,它是从腾讯收购的,所以是完全不同的账户和订单交易体系。 由于时间紧迫,我们把为商城订做的部分剥离,基于 3.0 架构对接拍拍又单独订做了一套,并独立部署,像下面这样。
Arch6.png

虽然在业务要求的时间点前完成了上线,但这样做也带来了明显的问题:
  1. 复制工程,定制业务开发,多套源码维护成本高
  2. 独立部署,至少双机房主备外加一个灰度集群,资源浪费大

 
以前我们都是面向业务去架构系统,如今新的业务变化形势下我们开始考虑面向平台去架构,在统一平台上跑多套业务,统一源码,统一部署,统一维护。 把业务服务继续拆分,剥离出最基础的 IM 服务,IM 通用服务,客服通用服务,而针对不同的业务特殊需求做最小化的定制服务开发。 部署方式则以平台形式部署,不同的业务方的服务跑在同一个平台上,但数据互相隔离。 服务继续被拆分的更微粒化,形成了一组服务矩阵(见下图)
Arch7.png

而部署方式,只需要在双机房建立两套对等集群,并另外建一个较小的灰度发布集群即可,所有不同业务都运行在统一平台集群上,如下图:
Arch8.png

更细粒度的服务意味着每个服务的开发更简单,代码量更小,依赖更少,隔离稳定性更高。 但更细粒度的服务也意味着更繁琐的运维监控管理,直到今年公司内部弹性私有云、缓存云、消息队列、部署、监控、日志等基础系统日趋完善, 使得实施这类细粒度划分的微服务架构成为可能,运维成本可控。 而从当初 1.0 的 1 种应用进程,到 3.0 的 6、7 种应用进程,再到 4.0 的 50+ 更细粒度的不同种应用进程。 每种进程再根据承载业务流量不同分配不同的实例数,真正的实例进程数会过千。 为了更好的监控和管理这些进程,为此专门定制了一套面向服务的运维管理系统,见下图:
Arch9.png

统一服务运维提供了实用的内部工具和库来帮助开发更健壮的微服务。 包括中心配置管理,流量埋点监控,数据库和缓存访问,运行时隔离,如下图所示是一个运行隔离的图示:
Arch10.png

细粒度的微服务做到了进程间隔离,严格的开发规范和工具库帮助实现了异步消息和异步 HTTP 来避免多个跨进程的同步长调用链。 进程内部通过切面方式引入了服务增强容器 Armor 来隔离线程, 并支持进程内的单独业务降级和同步转异步化执行。而所有这些工具和库服务都是为了两个目标:
  1. 让服务进程运行时状态可见
  2. 让服务进程运行时状态可被管理和改变


最后我们回到前文留下的一个悬念,就是关于消息投递模型的缺陷。 一开始我们在接入层检测到终端连接断开后,消息无法投递,再将消息缓存下来,等终端重连接上来再拉取离线消息。 这个模型在移动时代表现的很不好,因为移动网络的不稳定性,导致经常断链后重连。 而准确的检测网络连接断开是依赖一个网络超时的,导致检测可能不准确,引发消息假投递成功。 新的模型如下图所示,它不再依赖准确的网络连接检测,投递前待确认消息 id 被缓存,而消息体被持久存储。 等到终端接收确认返回后,该消息才算投妥,未确认的消息 id 再重新登陆后或重连接后作为离线消息推送。 这个模型不会产生消息假投妥导致的丢失,但可能导致消息重复,只需由客户终端按消息 id 去重即可。
Arch11.png

京东咚咚诞生之初正是京东技术转型到 Java 之时,经历这些年的发展,取得了很大的进步。 从草根走向专业,从弱小走向规模,从分散走向统一,从杂乱走向规范。 本文主要重心放在了几年来咚咚架构演进的过程,技术架构单独拿出来看我认为没有绝对的好与不好, 技术架构总是要放在彼时的背景下来看,要考虑业务的时效价值、团队的规模和能力、环境基础设施等等方面。 架构演进的生命周期适时匹配好业务的生命周期,才可能发挥最好的效果。
分享阅读原文:http://www.cnblogs.com/mindwind/p/5017591.html 

运维监控平台之Ganglia

开源技术Ansible 发表了文章 • 0 个评论 • 66 次浏览 • 2016-08-24 21:24 • 来自相关话题

Ganglia简介

Ganglia 是一款为 HPC(高性能计算)集群而设计的可扩展的分布式监控系统,它可以监视和显示集群中的节点的各种状态信息,它由运行在各个节点上的 gmond 守护进程来采集 CPU 、内存、硬盘利用率、 I/O 负载、网络流量情况等方面的数据,然后汇总到gmetad守护进程下,使用rrdtool 存储数据,最后将历史数据以曲线方式通过 PHP 页面呈现。
 
Ganglia 的特点如下:
 
良好的扩展性,分层架构设计能够适应大规模服务器集群的需要负载开销低,支持高并发广泛支持各种操作系统( UNIX 等)和 cpu 架构,支持虚拟
 

Ganglia组成

Ganglia 监控系统有三部分组成,分别是 gmond、 gmetad、 webfrontend,作用如下。
 
gmond: 即为 ganglia monitoring daemon,是一个守护进程,运行在每一个需要监测的节点上,用于收集本节点的信息并发送到其他节点,同时也接收其他节点发过了的数据,默认的监听端口为 8649。gmetad: 即为 ganglia meta daemon,是一个守护进程,运行在一个数据汇聚节点上,定期检查每个监测节点的 gmond 进程并从那里获取数据,然后将数据指标存储在本地 RRD 存储引擎中。webfrontend: 是一个基于 web 的图形化监控界面,需要和 Gmetad 安装在同一个节点上,它从 gmetad 取数据,并且读取 RRD 数据库,通过 
前台展示,界面美观、丰富,功能强大,结构如下图:





环境规划(centos6.7)
服务器端  172.16.80.117      
客户端    172.16.80.117 172.16.80.116 
 

Ganglia的安装

[root@centos02 tools]# wget wget
[root@centos02 tools]# rpm -ivh epel-release-6-8.noarch.rpm
[root@centos02 tools]# yum install ganglia-gmetad.x86_64 ganglia-gmond.x86_64 ganglia-gmond-python.x86_64 -y

修改服务端配置文件
[root@centos02 tools]# vim /etc/ganglia/gmetad.conf
data_source "my cluster" 172.16.80.117 172.16.80.116
gridname "MyGrid"


ganglia web的安装(基于LNMP环境)
[root@centos02 tools]# tar xf ganglia-web-3.7.2.tar.gz
[root@centos02 tools]# mv ganglia-web-3.7.2 /application/nginx/html/ganglia

修改ganglia web的php配置文件
[root@centos02 tools]# vim /application/nginx/html/ganglia/conf_default.php
$conf['gweb_confdir'] = "/application/nginx/html/ganglia";

nginx配置
[root@centos02 ganglia]# cat /application/nginx/conf/nginx.conf
worker_processes 2;
events {
worker_connections 1024;
}
http {


log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';



include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;

server {
listen 80;
server_name www.martin.com martin.com;

location / {
root html/zabbix;
index index.php index.html index.htm;
}


location ~ .*\.(php|php5)?$ {
root html/zabbix;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi.conf;
}

access_log logs/access_zabbix.log main;
}

server {
listen 80;
server_name ganglia.martin.com;

location / {
root html/ganglia;
index index.php index.html index.htm;
}


location ~ .*\.(php|php5)?$ {
root html/ganglia;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi.conf;
}

access_log logs/access_bbs.log main;

}

###status
server{
listen 80;
server_name status.martin.org;
location / {
stub_status on;
access_log off;
}
}

}

访问测试,报错如下
Fatal error:Errors were detected in your configuration.
DWOO compiled templates directory '/application/nginx/html/ganglia/dwoo/compiled' is not writeable.
Please adjust $conf['dwoo_compiled_dir'].
DWOO cache directory '/application/nginx/html/ganglia/dwoo/cache' is not writeable.
Please adjust $conf['dwoo_cache_dir'].
in /application/nginx-1.6.3/html/ganglia/eval_conf.php on line 126

解决办法:
[root@centos02 tools]# mkdir /application/nginx/html/ganglia/dwoo/compiled
[root@centos02 tools]# mkdir /application/nginx/html/ganglia/dwoo/cache

[root@centos02 tools]# chmod 777 /application/nginx/html/ganglia/dwoo/compiled
[root@centos02 tools]# chmod 777 /application/nginx/html/ganglia/dwoo/cache
[root@centos02 html]# chmod -R 777 /var/lib/ganglia/rrds


修改客户端配置文件(所有的客户端都需要做)
[root@centos02 tools]# vim /etc/ganglia/gmond.conf
cluster {
name = "my cluster" #这个名字要和服务器端定义的data_source后面的名字一样
owner = "unspecified"
latlong = "unspecified"
url = "unspecified"
}

udp_send_channel {
#bind_hostname = yes # Highly recommended, soon to be default.
# This option tells gmond to use a source address
# that resolves to the machine's hostname. Without
# this, the metrics may appear to come from any
# interface and the DNS names associated with
# those IPs will be used to create the RRDs.
# mcast_join = 239.2.11.71
host = 172.16.80.117 #这里我们采用单播方式,默认是组播
port = 8649
# ttl = 1
}

udp_recv_channel {
# mcast_join = 239.2.11.71
port = 8649
# bind = 239.2.11.71
retry_bind = true
# Size of the UDP buffer. If you are handling lots of metrics you really
# should bump it up to e.g. 10MB or even higher.
# buffer = 10485760
}
 

访问测试





这里是整个集群的一个总的汇总图,而不是单台服务器的图,下面我们打开单台服务器的图看看




再来看看对同一指标,每台服务器一起显示的图







扩展 Ganglia 监控功能的方法

默认安装完成的 Ganglia 仅向我们提供基础的系统监控信息,通过 Ganglia 插件可以实现两种扩展 Ganglia 监控功能的方法。
 
添加带内( in-band)插件,主要是通过gmetric命令来实现。这是通常使用的一种方法,主要是通过crontab方法并调用Ganglia的gmetric命令来向gmond 输入数据,进而实现统一监控。这种方法简单,对于少量的监控可以采用,但是对于大规模自定义监控时,监控数据难以统一管理。添加一些其他来源的带外( out-of-band)插件,主要是通过 C 或者 Python 接口来实现。
在 Ganglia3.1.x 版本以后,增加了 C 或 Python 接口,通过这个接口可以自定义数据收集模块,并且可以将这些模块直接插入到 gmond 中以监控用户自定义的应用。
 
这里我们举例通过带外扩展的方式 来监控nginx的运行状态配置 ganglia 客户端,收集 nginx_status 数据
[root@centos02 nginx_status]# pwd
/tools/gmond_python_modules-master/nginx_status
[root@centos02 nginx_status]# cp conf.d/nginx_status.pyconf /etc/ganglia/conf.d/
[root@centos02 nginx_status]# cp python_modules/nginx_status.py /usr/lib64/ganglia/python_modules/
[root@centos02 nginx_status]# cp graph.d/nginx_* /application/nginx/html/ganglia/graph.d/

[root@centos02 mysql]# cat /etc/ganglia/conf.d/nginx_status.pyconf
#

modules {
module {
name = 'nginx_status'
language = 'python'

param status_url {
value = 'http://status.martin.org/'
}
param nginx_bin {
value = '/application/nginx/sbin/nginx'
}
param refresh_rate {
value = '15'
}
}
}

collection_group {
collect_once = yes
time_threshold = 20

metric {
name = 'nginx_server_version'
title = "Nginx Version"
}
}

collection_group {
collect_every = 10
time_threshold = 20

metric {
name = "nginx_active_connections"
title = "Total Active Connections"
value_threshold = 1.0
}

metric {
name = "nginx_accepts"
title = "Total Connections Accepted"
value_threshold = 1.0
}

metric {
name = "nginx_handled"
title = "Total Connections Handled"
value_threshold = 1.0
}

metric {
name = "nginx_requests"
title = "Total Requests"
value_threshold = 1.0
}

metric {
name = "nginx_reading"
title = "Connections Reading"
value_threshold = 1.0
}

metric {
name = "nginx_writing"
title = "Connections Writing"
value_threshold = 1.0
}

metric {
name = "nginx_waiting"
title = "Connections Waiting"
value_threshold = 1.0
}
}完成上面的所有步骤后,重启 Ganglia 客户端 gmond 服务,在客户端通过“ gmond–m”命令可以查看支持的模板,最后就可以在 Ganglia web 界面查看 Nginx 的运行状态








阅读分享授权转载:http://huaxin.blog.51cto.com/903026/1841208 查看全部


Ganglia简介


Ganglia 是一款为 HPC(高性能计算)集群而设计的可扩展的分布式监控系统,它可以监视和显示集群中的节点的各种状态信息,它由运行在各个节点上的 gmond 守护进程来采集 CPU 、内存、硬盘利用率、 I/O 负载、网络流量情况等方面的数据,然后汇总到gmetad守护进程下,使用rrdtool 存储数据,最后将历史数据以曲线方式通过 PHP 页面呈现。
 
Ganglia 的特点如下:
 
  • 良好的扩展性,分层架构设计能够适应大规模服务器集群的需要
  • 负载开销低,支持高并发
  • 广泛支持各种操作系统( UNIX 等)和 cpu 架构,支持虚拟

 


Ganglia组成


Ganglia 监控系统有三部分组成,分别是 gmond、 gmetad、 webfrontend,作用如下。
 
  • gmond: 即为 ganglia monitoring daemon,是一个守护进程,运行在每一个需要监测的节点上,用于收集本节点的信息并发送到其他节点,同时也接收其他节点发过了的数据,默认的监听端口为 8649。
  • gmetad: 即为 ganglia meta daemon,是一个守护进程,运行在一个数据汇聚节点上,定期检查每个监测节点的 gmond 进程并从那里获取数据,然后将数据指标存储在本地 RRD 存储引擎中。
  • webfrontend: 是一个基于 web 的图形化监控界面,需要和 Gmetad 安装在同一个节点上,它从 gmetad 取数据,并且读取 RRD 数据库,通过 

前台展示,界面美观、丰富,功能强大,结构如下图:
ganglia.png


环境规划(centos6.7)
服务器端  172.16.80.117      
客户端    172.16.80.117 172.16.80.116 
 


Ganglia的安装


[root@centos02 tools]# wget wget 
[root@centos02 tools]# rpm -ivh epel-release-6-8.noarch.rpm
[root@centos02 tools]# yum install ganglia-gmetad.x86_64 ganglia-gmond.x86_64 ganglia-gmond-python.x86_64 -y

修改服务端配置文件
[root@centos02 tools]# vim /etc/ganglia/gmetad.conf
data_source "my cluster" 172.16.80.117 172.16.80.116
gridname "MyGrid"


ganglia web的安装(基于LNMP环境)
[root@centos02 tools]# tar xf ganglia-web-3.7.2.tar.gz
[root@centos02 tools]# mv ganglia-web-3.7.2 /application/nginx/html/ganglia

修改ganglia web的php配置文件
[root@centos02 tools]# vim /application/nginx/html/ganglia/conf_default.php
$conf['gweb_confdir'] = "/application/nginx/html/ganglia";

nginx配置
[root@centos02 ganglia]# cat /application/nginx/conf/nginx.conf
worker_processes 2;
events {
worker_connections 1024;
}
http {


log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';



include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;

server {
listen 80;
server_name www.martin.com martin.com;

location / {
root html/zabbix;
index index.php index.html index.htm;
}


location ~ .*\.(php|php5)?$ {
root html/zabbix;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi.conf;
}

access_log logs/access_zabbix.log main;
}

server {
listen 80;
server_name ganglia.martin.com;

location / {
root html/ganglia;
index index.php index.html index.htm;
}


location ~ .*\.(php|php5)?$ {
root html/ganglia;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi.conf;
}

access_log logs/access_bbs.log main;

}

###status
server{
listen 80;
server_name status.martin.org;
location / {
stub_status on;
access_log off;
}
}

}

访问测试,报错如下
Fatal error:Errors were detected in your configuration.
DWOO compiled templates directory '/application/nginx/html/ganglia/dwoo/compiled' is not writeable.
Please adjust $conf['dwoo_compiled_dir'].
DWOO cache directory '/application/nginx/html/ganglia/dwoo/cache' is not writeable.
Please adjust $conf['dwoo_cache_dir'].
in /application/nginx-1.6.3/html/ganglia/eval_conf.php on line 126

解决办法:
[root@centos02 tools]# mkdir /application/nginx/html/ganglia/dwoo/compiled
[root@centos02 tools]# mkdir /application/nginx/html/ganglia/dwoo/cache

[root@centos02 tools]# chmod 777 /application/nginx/html/ganglia/dwoo/compiled
[root@centos02 tools]# chmod 777 /application/nginx/html/ganglia/dwoo/cache
[root@centos02 html]# chmod -R 777 /var/lib/ganglia/rrds


修改客户端配置文件(所有的客户端都需要做)
[root@centos02 tools]# vim /etc/ganglia/gmond.conf
cluster {
name = "my cluster" #这个名字要和服务器端定义的data_source后面的名字一样
owner = "unspecified"
latlong = "unspecified"
url = "unspecified"
}

udp_send_channel {
#bind_hostname = yes # Highly recommended, soon to be default.
# This option tells gmond to use a source address
# that resolves to the machine's hostname. Without
# this, the metrics may appear to come from any
# interface and the DNS names associated with
# those IPs will be used to create the RRDs.
# mcast_join = 239.2.11.71
host = 172.16.80.117 #这里我们采用单播方式,默认是组播
port = 8649
# ttl = 1
}

udp_recv_channel {
# mcast_join = 239.2.11.71
port = 8649
# bind = 239.2.11.71
retry_bind = true
# Size of the UDP buffer. If you are handling lots of metrics you really
# should bump it up to e.g. 10MB or even higher.
# buffer = 10485760
}

 


访问测试


ganglia_test.png

这里是整个集群的一个总的汇总图,而不是单台服务器的图,下面我们打开单台服务器的图看看
HostReport.png

再来看看对同一指标,每台服务器一起显示的图
duibi.png




扩展 Ganglia 监控功能的方法


默认安装完成的 Ganglia 仅向我们提供基础的系统监控信息,通过 Ganglia 插件可以实现两种扩展 Ganglia 监控功能的方法。
 
  1. 添加带内( in-band)插件,主要是通过gmetric命令来实现。这是通常使用的一种方法,主要是通过crontab方法并调用Ganglia的gmetric命令来向gmond 输入数据,进而实现统一监控。这种方法简单,对于少量的监控可以采用,但是对于大规模自定义监控时,监控数据难以统一管理。
  2. 添加一些其他来源的带外( out-of-band)插件,主要是通过 C 或者 Python 接口来实现。

在 Ganglia3.1.x 版本以后,增加了 C 或 Python 接口,通过这个接口可以自定义数据收集模块,并且可以将这些模块直接插入到 gmond 中以监控用户自定义的应用。
 
这里我们举例通过带外扩展的方式 来监控nginx的运行状态
配置 ganglia 客户端,收集 nginx_status 数据
[root@centos02 nginx_status]# pwd
/tools/gmond_python_modules-master/nginx_status
[root@centos02 nginx_status]# cp conf.d/nginx_status.pyconf /etc/ganglia/conf.d/
[root@centos02 nginx_status]# cp python_modules/nginx_status.py /usr/lib64/ganglia/python_modules/
[root@centos02 nginx_status]# cp graph.d/nginx_* /application/nginx/html/ganglia/graph.d/

[root@centos02 mysql]# cat /etc/ganglia/conf.d/nginx_status.pyconf
#

modules {
module {
name = 'nginx_status'
language = 'python'

param status_url {
value = 'http://status.martin.org/'
}
param nginx_bin {
value = '/application/nginx/sbin/nginx'
}
param refresh_rate {
value = '15'
}
}
}

collection_group {
collect_once = yes
time_threshold = 20

metric {
name = 'nginx_server_version'
title = "Nginx Version"
}
}

collection_group {
collect_every = 10
time_threshold = 20

metric {
name = "nginx_active_connections"
title = "Total Active Connections"
value_threshold = 1.0
}

metric {
name = "nginx_accepts"
title = "Total Connections Accepted"
value_threshold = 1.0
}

metric {
name = "nginx_handled"
title = "Total Connections Handled"
value_threshold = 1.0
}

metric {
name = "nginx_requests"
title = "Total Requests"
value_threshold = 1.0
}

metric {
name = "nginx_reading"
title = "Connections Reading"
value_threshold = 1.0
}

metric {
name = "nginx_writing"
title = "Connections Writing"
value_threshold = 1.0
}

metric {
name = "nginx_waiting"
title = "Connections Waiting"
value_threshold = 1.0
}
}
完成上面的所有步骤后,重启 Ganglia 客户端 gmond 服务,在客户端通过“ gmond–m”命令可以查看支持的模板,最后就可以在 Ganglia web 界面查看 Nginx 的运行状态
NginxStatic.png

NginxMonitor.png

阅读分享授权转载:http://huaxin.blog.51cto.com/903026/1841208

Python使用正则收集IP信息

编程语言Not see︶ 发表了文章 • 0 个评论 • 65 次浏览 • 2016-08-24 14:38 • 来自相关话题

#!/usr/bin/env python

import re
from subprocess import Popen, PIPE

def getIfconfig():
p = Popen(['ifconfig'], stdout=PIPE)
data = p.stdout.read().split('\n\n')
return [i for i in data if i and not i.startswith('lo')]

def parseIfconfig(data):
re_devname = re.compile(r'(br|eth|em|virbr|lo|bond)[\d:]+',re.M)
re_mac = re.compile(r'HWaddr ([0-9A-F:]{17})', re.M)
re_ip = re.compile('inet addr:([\d\.]{7,15})', re.M)
devname = re_devname.search(data)
if devname:
devname = devname.group()
else:
devname = ''
mac = re_mac.search(data)
if mac:
mac = mac.group(1)
else:
mac = ''
ip = re_ip.search(data)
if ip:
ip = ip.group(1)
else:
ip = ''
return {devname: [ip, mac]}

if __name__ == '__main__':
data = getIfconfig()
for i in data:
print parseIfconfig(i) 查看全部
#!/usr/bin/env python

import re
from subprocess import Popen, PIPE

def getIfconfig():
p = Popen(['ifconfig'], stdout=PIPE)
data = p.stdout.read().split('\n\n')
return [i for i in data if i and not i.startswith('lo')]

def parseIfconfig(data):
re_devname = re.compile(r'(br|eth|em|virbr|lo|bond)[\d:]+',re.M)
re_mac = re.compile(r'HWaddr ([0-9A-F:]{17})', re.M)
re_ip = re.compile('inet addr:([\d\.]{7,15})', re.M)
devname = re_devname.search(data)
if devname:
devname = devname.group()
else:
devname = ''
mac = re_mac.search(data)
if mac:
mac = mac.group(1)
else:
mac = ''
ip = re_ip.search(data)
if ip:
ip = ip.group(1)
else:
ip = ''
return {devname: [ip, mac]}

if __name__ == '__main__':
data = getIfconfig()
for i in data:
print parseIfconfig(i)

Docker的Web Ui管理和监控系统海鸥

开源项目OpenSkill 发表了文章 • 0 个评论 • 623 次浏览 • 2016-08-23 00:33 • 来自相关话题

功能介绍

Seagull是一套友好的Web用户界面,用来全面的管理和监控Docker管理系统。
易于安装和Docker容器内卸载一键启动/停止/删除容器和image超快速(<10ms)的搜索和过滤支持多主机管理和监控国际化包括英语,中国,德国和法国
欲了解更多信息,请访问dockerseagull.com ,看三分钟的视频和官方的幻灯片 。
 

安装

安装非常简单,一条命令搞定,就是so easy!docker run -d -p 10086:10086 -v /var/run/docker.sock:/var/run/docker.sock tobegit3hub/seagull 或者运行:docker-compose up -d然后直接访问http://127.0.0.1:10086监控你的Docker容器;对于boot2docker用户,请运行boot2docker ip找到真正的IP地址。
 

Web效果图










多主机

海鸥支持监视多个服务器。 请确保你启动Docker的守护进程是这个样子 docker -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock -api-enable-cors=true -d

参与开发

海鸥是用Go和JavaScript实现的,使用了Beego、AngularJS、Bootstrap、Bower、JQuery和Docker等工具。你可以Fork这个项目并且按你的需求发送Pull-request。
配置Go路径然后尝试echo $GOPATHgo get github.com/astaxie/beegogo get github.com/beego/beegit clone https://github.com/tobegit3hub/seagull.git $GOPATH/src/github.com/tobegit3hub/seagull/go build seagull.go或者运行bee run seagull来调试./seagull或者运行sudo ./seagull来访问/var/run/docker.sock
更详细的海鸥设计和实施,还有非常好完善的帮助文档 。

注意

问题 #2表明,如果海鸥的IP和端口暴露每个人都可以访问您的Docker守护进程。 为了安全,你可以绑定到localhost来限制访问。
 
项目地址:https://github.com/tobegit3hub/seagull
  查看全部


功能介绍


Seagull是一套友好的Web用户界面,用来全面的管理和监控Docker管理系统。
  • 易于安装和Docker容器内卸载
  • 一键启动/停止/删除容器和image
  • 超快速(<10ms)的搜索和过滤
  • 支持多主机管理和监控
  • 国际化包括英语,中国,德国和法国

欲了解更多信息,请访问dockerseagull.com ,看三分钟的视频和官方的幻灯片
 


安装


安装非常简单,一条命令搞定,就是so easy!
docker run -d -p 10086:10086 -v /var/run/docker.sock:/var/run/docker.sock tobegit3hub/seagull 
或者运行:
docker-compose up -d
然后直接访问http://127.0.0.1:10086监控你的Docker容器;对于boot2docker用户,请运行boot2docker ip找到真正的IP地址。
 


Web效果图


docker_web_ui.png

DockerWebUI.png


多主机


海鸥支持监视多个服务器。 请确保你启动Docker的守护进程是这个样子
 docker -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock -api-enable-cors=true -d 


参与开发


海鸥是用Go和JavaScript实现的,使用了Beego、AngularJS、Bootstrap、Bower、JQuery和Docker等工具。你可以Fork这个项目并且按你的需求发送Pull-request。
  • 配置Go路径然后尝试echo $GOPATH
  • go get github.com/astaxie/beego
  • go get github.com/beego/bee
  • git clone https://github.com/tobegit3hub/seagull.git $GOPATH/src/github.com/tobegit3hub/seagull/
  • go build seagull.go或者运行bee run seagull来调试
  • ./seagull或者运行sudo ./seagull来访问/var/run/docker.sock

更详细的海鸥设计和实施,还有非常好完善的帮助文档 。


注意


问题 #2表明,如果海鸥的IP和端口暴露每个人都可以访问您的Docker守护进程。 为了安全,你可以绑定到localhost来限制访问。
 
项目地址:https://github.com/tobegit3hub/seagull
 


Python3中异常处理常用的三种方法

编程语言小白菜 发表了文章 • 0 个评论 • 68 次浏览 • 2016-08-22 23:13 • 来自相关话题

一般我们我们想捕获python的异常写入到log,做处理的话,一般用try语句来做处理,大概语法如下:try:
语句1
语句2
.
.
语句N
except ........ :
do something .......但是你并不知道"语句1至语句N"哪个会出现什么样的错误,但你还要做异常处理,且想把出现的异常打印出来,并不停止程序的运行,所以在"except ......"语句就起作用了。
 
方法一:捕获所有异常Python2如下:
try:
语句1
语句2
.....
语句N
except Exception,e:
print Exception,":",e

Python3如下:
try:
语句1
语句2
.....
语句N
except Exception as e:
print(Exception, ":", e)例子如下:try:
a = 1
b = a
c = w
except Exception as e:
print(Exception, ":", e)

结果为:
<class 'Exception'> : name 'w' is not defined
 方法二:采用sys模块回溯最后的异常
sys.exc_info() 会返回一个3值元表,其中包含调用该命令时捕获的异常。
这个元表的内容为 (type, value, traceback) ,其中:
type 从获取到的异常中得到类型名称,它是BaseException 的子类;value 是捕获到的异常实例;traceback 是一个 traceback 对象,下面会详述。
import sys
try:
w = abs(-1)
list.append(w)
except:
info = sys.exc_info()
print(info[0], ":", info[1])

# 结果如下:
<class 'TypeError'> : descriptor 'append' requires a 'list' object but received a 'int'sys.last_traceback 包含的内容与 sys.exc_info() 相同,但它主要用于调试,并不总是被定义。
 
三、采用traceback模块查看异常
trackback 模块用来精确模仿 python3 解析器的 stack trace 行为。在程序中应该尽量使用这个模块。
traceback.print_exc() 可以直接打印当前的异常。import traceback
try:
raise
except:
traceback.print_exc()traceback.print_tb() 用来打印上面提到的 trackback 对象。import sys,traceback
try:
raise
except:
t,v,tb = sys.exc_info()
traceback.print_tb(tb)traceback.print_exception() 可以直接打印 sys.exc_info()提供的元表。import sys,traceback
try:
raise
except:
traceback.print_exception(*sys.exc_info())其实,下面两句是等价的:
traceback.print_exc()traceback.print_exception(*sys.exc_info())
 
traceback 提供的参数可以将 print 的内容写入到文件中import traceback
try:
a=b
b=c
except:
f=open("log.txt",'a')
traceback.print_exc(file=f)
f.flush()
f.close()参考:
https://docs.python.org/3/library/traceback.html?highlight=print_tb#traceback.print_exc
https://docs.python.org/3/tutorial/errors.html 查看全部
一般我们我们想捕获python的异常写入到log,做处理的话,一般用try语句来做处理,大概语法如下:
try:
语句1
语句2
.
.
语句N
except ........ :
do something .......
但是你并不知道"语句1至语句N"哪个会出现什么样的错误,但你还要做异常处理,且想把出现的异常打印出来,并不停止程序的运行,所以在"except ......"语句就起作用了。
 
方法一:捕获所有异常
Python2如下:
try:
语句1
语句2
.....
语句N
except Exception,e:
print Exception,":",e

Python3如下:
try:
语句1
语句2
.....
语句N
except Exception as e:
print(Exception, ":", e)
例子如下:
try:
a = 1
b = a
c = w
except Exception as e:
print(Exception, ":", e)

结果为:
<class 'Exception'> : name 'w' is not defined

 方法二:采用sys模块回溯最后的异常
sys.exc_info() 会返回一个3值元表,其中包含调用该命令时捕获的异常。
这个元表的内容为 (type, value, traceback) ,其中:
  • type 从获取到的异常中得到类型名称,它是BaseException 的子类;
  • value 是捕获到的异常实例;
  • traceback 是一个 traceback 对象,下面会详述。

import sys
try:
w = abs(-1)
list.append(w)
except:
info = sys.exc_info()
print(info[0], ":", info[1])

# 结果如下:
<class 'TypeError'> : descriptor 'append' requires a 'list' object but received a 'int'
sys.last_traceback 包含的内容与 sys.exc_info() 相同,但它主要用于调试,并不总是被定义。
 
三、采用traceback模块查看异常
trackback 模块用来精确模仿 python3 解析器的 stack trace 行为。在程序中应该尽量使用这个模块。
traceback.print_exc() 可以直接打印当前的异常。
import traceback
try:
raise
except:
traceback.print_exc()
traceback.print_tb() 用来打印上面提到的 trackback 对象。
import sys,traceback
try:
raise
except:
t,v,tb = sys.exc_info()
traceback.print_tb(tb)
traceback.print_exception() 可以直接打印 sys.exc_info()提供的元表。
import sys,traceback
try:
raise
except:
traceback.print_exception(*sys.exc_info())
其实,下面两句是等价的:
  • traceback.print_exc()
  • traceback.print_exception(*sys.exc_info())

 
traceback 提供的参数可以将 print 的内容写入到文件中
import traceback
try:
a=b
b=c
except:
f=open("log.txt",'a')
traceback.print_exc(file=f)
f.flush()
f.close()
参考:
https://docs.python.org/3/library/traceback.html?highlight=print_tb#traceback.print_exc
https://docs.python.org/3/tutorial/errors.html

FFMpeg和Zabbix暴露的漏洞

开源技术Geek小A 发表了文章 • 0 个评论 • 73 次浏览 • 2016-08-22 18:17 • 来自相关话题

一、FFMpeg缓冲区溢出高危漏洞安全预警

FFMpeg发布新版本,修复了之前版本存在的高危漏洞,请您及时修补。
 
影响范围:
FFMpeg <=3.1.1,且使用了swf解析模块。
 
修复方案:
升级到版本FFMpeg 3.1.2
 
漏洞详情:
FFMpeg在解码swf文件时存在一个缓冲区溢出高危漏洞(CVE-2016-6671)。漏洞主要存在于在对swf文件进行raw解码时,计算解码后的数据大小存在错误,导致写入数据的大小超过申请内存空间的大小,造成缓冲区内存溢出。该漏洞在一定条件下能导致任意代码执行。
 
参考:http://seclists.org/oss-sec/2016/q3/271
 

二、zabbix的SQL注入高危漏洞

近日,zabbix被爆出两个高危SQL注入漏洞,zabbix的jsrpc的profileIdx2参数存在insert方式的SQL注入漏洞,攻击者无需授权登陆即可登陆zabbix管理系统,也可通过script等功能轻易直接获取zabbix服务器的操作系统权限。
 
影响范围:
攻击成本:低
危害程度:高
是否登陆:不需要
影响范围:2.2.x, 3.0.0-3.0.3。(其他版本未经测试)
 
漏洞测试:
在zabbix的访问地址后面加上如下url:
/jsrpc.php?sid=0bcd4ade648214dc&type=9&method=screen.get&tim
estamp=1471403798083&mode=2&screenid=&groupid=&hostid=0&pageFile=hi
story.php&profileIdx=web.item.graph&profileIdx2=2'3297&updateProfil
e=true&screenitemid=&period=3600&stime=20160817050632&resourcetype=
17&itemids%5B23297%5D=23297&action=showlatest&filter=&filter_task=&
mark_color=1输出结果,出现如下图黄色关键字表示漏洞存在:




 
补充:
以上为仅为漏洞验证测试方式。攻击者可以通过进一步构造语句进行错误型sql注射,无需获取和破解加密的管理员密码。有经验的攻击者可以直接通过获取admin的sessionid来根据结构算法构造sid,替换cookie直接以管理员身份登陆。
 
修复方案:升级到最新版吧,据说3.0.4版本已经修补,但是我发现并没有,所以如果你是nginx,可以在server段加下面试试,然后打开日志,看看有没有误判,这是临时暴力解决方案
if ($request_uri ~ ^(.+\.php)(.*)$) {
set $req $2;
}
if ($req ~* "union[+|(%20)]") {
return 503;
}
if ($req ~* "and[+|(%20)]") {
return 503;
}
if ($req ~* "select[+|(%20)]") {
return 503;
}
 漏洞详情:
zabbix jsrpc.php的profileIdx2参数和latest.php的toggle_ids参数均存在SQL注入,属于高危漏洞。在开启Guest或者无用户的情况下不需要登录即可实现注入(默认开启Guest,且Guest默认密码为空);未开启Guest和有用户的情况下则需要鉴权通过方可实现注入。攻击者可以完全获取数据库中信息,获取管理员身份,甚至控制服务器权限。更多详情见:http://seclists.org/fulldisclosure/2016/Aug/82 查看全部


一、FFMpeg缓冲区溢出高危漏洞安全预警


FFMpeg发布新版本,修复了之前版本存在的高危漏洞,请您及时修补。
 
影响范围:
FFMpeg <=3.1.1,且使用了swf解析模块。
 
修复方案:
升级到版本FFMpeg 3.1.2
 
漏洞详情:
FFMpeg在解码swf文件时存在一个缓冲区溢出高危漏洞(CVE-2016-6671)。漏洞主要存在于在对swf文件进行raw解码时,计算解码后的数据大小存在错误,导致写入数据的大小超过申请内存空间的大小,造成缓冲区内存溢出。该漏洞在一定条件下能导致任意代码执行。
 
参考:http://seclists.org/oss-sec/2016/q3/271
 


二、zabbix的SQL注入高危漏洞


近日,zabbix被爆出两个高危SQL注入漏洞,zabbix的jsrpc的profileIdx2参数存在insert方式的SQL注入漏洞,攻击者无需授权登陆即可登陆zabbix管理系统,也可通过script等功能轻易直接获取zabbix服务器的操作系统权限。
 
影响范围
攻击成本:低
危害程度:高
是否登陆:不需要
影响范围:2.2.x, 3.0.0-3.0.3。(其他版本未经测试)
 
漏洞测试:
在zabbix的访问地址后面加上如下url:
/jsrpc.php?sid=0bcd4ade648214dc&type=9&method=screen.get&tim
estamp=1471403798083&mode=2&screenid=&groupid=&hostid=0&pageFile=hi
story.php&profileIdx=web.item.graph&profileIdx2=2'3297&updateProfil
e=true&screenitemid=&period=3600&stime=20160817050632&resourcetype=
17&itemids%5B23297%5D=23297&action=showlatest&filter=&filter_task=&
mark_color=1
输出结果,出现如下图黄色关键字表示漏洞存在:
zabbix_bug.png

 
补充:
  • 以上为仅为漏洞验证测试方式。
  • 攻击者可以通过进一步构造语句进行错误型sql注射,无需获取和破解加密的管理员密码。
  • 有经验的攻击者可以直接通过获取admin的sessionid来根据结构算法构造sid,替换cookie直接以管理员身份登陆。

 
修复方案:升级到最新版吧,据说3.0.4版本已经修补,但是我发现并没有,所以如果你是nginx,可以在server段加下面试试,然后打开日志,看看有没有误判,这是临时暴力解决方案
       if ($request_uri ~ ^(.+\.php)(.*)$) {
set $req $2;
}
if ($req ~* "union[+|(%20)]") {
return 503;
}
if ($req ~* "and[+|(%20)]") {
return 503;
}
if ($req ~* "select[+|(%20)]") {
return 503;
}

 漏洞详情:
zabbix jsrpc.php的profileIdx2参数和latest.php的toggle_ids参数均存在SQL注入,属于高危漏洞。在开启Guest或者无用户的情况下不需要登录即可实现注入(默认开启Guest,且Guest默认密码为空);未开启Guest和有用户的情况下则需要鉴权通过方可实现注入。攻击者可以完全获取数据库中信息,获取管理员身份,甚至控制服务器权限。更多详情见:http://seclists.org/fulldisclosure/2016/Aug/82

MySQL Server has gone away报错分析

数据库being 发表了文章 • 0 个评论 • 74 次浏览 • 2016-08-21 23:59 • 来自相关话题

在平时和开发的交流以及在论坛回答问题的或称中会发现这个问题被问及的频率非常高。 程序中报错: MySQL server has gone away 是什么意思? 如何避免? 因此,感觉有必要总结一下发生这个问题的原因。
 

一、MySQL 服务宕了​

判断是否属于这个原因的方法很简单,执行以下命令,查看mysql的运行时长
$ mysql -uroot -p -e "show global status like 'uptime';"
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Uptime | 68928 |
+---------------+-------+
1 row in set (0.04 sec)或者查看MySQL的报错日志,看看有没有重启的信息
$ tail /var/log/mysql/error.log
130101 22:22:30 InnoDB: Initializing buffer pool, size = 256.0M
130101 22:22:30 InnoDB: Completed initialization of buffer pool
130101 22:22:30 InnoDB: highest supported file format is Barracuda.
130101 22:22:30 InnoDB: 1.1.8 started; log sequence number 63444325509
130101 22:22:30 [Note] Server hostname (bind-address): '127.0.0.1'; port: 3306
130101 22:22:30 [Note] - '127.0.0.1' resolves to '127.0.0.1';
130101 22:22:30 [Note] Server socket created on IP: '127.0.0.1'.
130101 22:22:30 [Note] Event Scheduler: Loaded 0 events
130101 22:22:30 [Note] /usr/sbin/mysqld: ready for connections.
Version: '5.5.28-cll' socket: '/var/lib/mysql/mysql.sock' port: 3306 MySQL Community Server (GPL)如果uptime数值很大,表明mysql服务运行了很久了。说明最近服务没有重启过。 如果日志没有相关信息,也说明mysql服务最近没有重启过,可以继续检查下面几项内容。
 

二、连接超时

如果程序使用的是长连接,则这种情况的可能性会比较大。 即,某个长连接很久没有新的请求发起,达到了server端的timeout,被server强行关闭。 此后再通过这个connection发起查询的时候,就会报错server has gone away
$ mysql -uroot -p -e "show global variables like '%timeout';"
+----------------------------+----------+
| Variable_name | Value |
+----------------------------+----------+
| connect_timeout | 30 |
| delayed_insert_timeout | 300 |
| innodb_lock_wait_timeout | 50 |
| innodb_rollback_on_timeout | OFF |
| interactive_timeout | 28800 |
| lock_wait_timeout | 31536000 |
| net_read_timeout | 30 |
| net_write_timeout | 60 |
| slave_net_timeout | 3600 |
| wait_timeout | 28800 |
+----------------------------+----------+
mysql> SET SESSION wait_timeout=5;


# Wait 10 seconds

mysql> SELECT NOW();
ERROR 2006 (HY000): MySQL server has gone away
No connection. Trying to reconnect...
Connection id: 132361
Current database: *** NONE ***

+---------------------+
| NOW() |
+---------------------+
| 2013-01-02 11:31:15 |
+---------------------+
1 row in set (0.00 sec)

三、进程在server端被主动kill

这种情况和情况2相似,只是发起者是DBA或者其他job。发现有长时间的慢查询执行kill xxx导致。
$ mysql -uroot -p -e "show global status like 'com_kill'"
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Com_kill | 0 |
+---------------+-------+

四、Your SQL statement was too large.

当查询的结果集超过 max_allowed_packet 也会出现这样的报错。定位方法是打出相关报错的语句。 用select * into outfile 的方式导出到文件,查看文件大小是否超过max_allowed_packet ,如果超过则需要调整参数,或者优化语句。
mysql> show global variables like 'max_allowed_packet';
+--------------------+---------+
| Variable_name | Value |
+--------------------+---------+
| max_allowed_packet | 1048576 |
+--------------------+---------+
1 row in set (0.00 sec)

# 修改参数:

mysql> set global max_allowed_packet=1024*1024*16;
mysql> show global variables like 'max_allowed_packet';
+--------------------+----------+
| Variable_name | Value |
+--------------------+----------+
| max_allowed_packet | 16777216 |
+--------------------+----------+
1 row in set (0.00 sec)英文原文:http://ronaldbradford.com/blog/sqlstatehy000-general-error-2006-mysql-server-has-gone-away-2013-01-02/ 查看全部
在平时和开发的交流以及在论坛回答问题的或称中会发现这个问题被问及的频率非常高。 程序中报错: MySQL server has gone away 是什么意思? 如何避免? 因此,感觉有必要总结一下发生这个问题的原因。
 


一、MySQL 服务宕了​


判断是否属于这个原因的方法很简单,执行以下命令,查看mysql的运行时长
$ mysql -uroot -p -e "show global status like 'uptime';"
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Uptime | 68928 |
+---------------+-------+
1 row in set (0.04 sec)
或者查看MySQL的报错日志,看看有没有重启的信息
$ tail /var/log/mysql/error.log
130101 22:22:30 InnoDB: Initializing buffer pool, size = 256.0M
130101 22:22:30 InnoDB: Completed initialization of buffer pool
130101 22:22:30 InnoDB: highest supported file format is Barracuda.
130101 22:22:30 InnoDB: 1.1.8 started; log sequence number 63444325509
130101 22:22:30 [Note] Server hostname (bind-address): '127.0.0.1'; port: 3306
130101 22:22:30 [Note] - '127.0.0.1' resolves to '127.0.0.1';
130101 22:22:30 [Note] Server socket created on IP: '127.0.0.1'.
130101 22:22:30 [Note] Event Scheduler: Loaded 0 events
130101 22:22:30 [Note] /usr/sbin/mysqld: ready for connections.
Version: '5.5.28-cll' socket: '/var/lib/mysql/mysql.sock' port: 3306 MySQL Community Server (GPL)
如果uptime数值很大,表明mysql服务运行了很久了。说明最近服务没有重启过。 如果日志没有相关信息,也说明mysql服务最近没有重启过,可以继续检查下面几项内容。
 


二、连接超时


如果程序使用的是长连接,则这种情况的可能性会比较大。 即,某个长连接很久没有新的请求发起,达到了server端的timeout,被server强行关闭。 此后再通过这个connection发起查询的时候,就会报错server has gone away
$ mysql -uroot -p -e "show global variables like '%timeout';"
+----------------------------+----------+
| Variable_name | Value |
+----------------------------+----------+
| connect_timeout | 30 |
| delayed_insert_timeout | 300 |
| innodb_lock_wait_timeout | 50 |
| innodb_rollback_on_timeout | OFF |
| interactive_timeout | 28800 |
| lock_wait_timeout | 31536000 |
| net_read_timeout | 30 |
| net_write_timeout | 60 |
| slave_net_timeout | 3600 |
| wait_timeout | 28800 |
+----------------------------+----------+
mysql> SET SESSION wait_timeout=5;


# Wait 10 seconds

mysql> SELECT NOW();
ERROR 2006 (HY000): MySQL server has gone away
No connection. Trying to reconnect...
Connection id: 132361
Current database: *** NONE ***

+---------------------+
| NOW() |
+---------------------+
| 2013-01-02 11:31:15 |
+---------------------+
1 row in set (0.00 sec)


三、进程在server端被主动kill


这种情况和情况2相似,只是发起者是DBA或者其他job。发现有长时间的慢查询执行kill xxx导致。
$ mysql -uroot -p -e "show global status like 'com_kill'"
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| Com_kill | 0 |
+---------------+-------+


四、Your SQL statement was too large.


当查询的结果集超过 max_allowed_packet 也会出现这样的报错。定位方法是打出相关报错的语句。 用select * into outfile 的方式导出到文件,查看文件大小是否超过max_allowed_packet ,如果超过则需要调整参数,或者优化语句。
mysql> show global variables like 'max_allowed_packet';
+--------------------+---------+
| Variable_name | Value |
+--------------------+---------+
| max_allowed_packet | 1048576 |
+--------------------+---------+
1 row in set (0.00 sec)

# 修改参数:

mysql> set global max_allowed_packet=1024*1024*16;
mysql> show global variables like 'max_allowed_packet';
+--------------------+----------+
| Variable_name | Value |
+--------------------+----------+
| max_allowed_packet | 16777216 |
+--------------------+----------+
1 row in set (0.00 sec)
英文原文:http://ronaldbradford.com/blog/sqlstatehy000-general-error-2006-mysql-server-has-gone-away-2013-01-02/

Python的生成器和迭代器

编程语言采菊篱下 发表了文章 • 0 个评论 • 77 次浏览 • 2016-08-19 18:39 • 来自相关话题

生成器

通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。
 
 
所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器:generator。
 
 
要创建一个generator,有很多种方法。第一种方法很简单,只要把一个列表生成式的[]改成(),就创建了一个generator:>>> L = [x * x for x in range(5)]
>>> L
[0, 1, 4, 9, 16]
>>> g = (x * x for x in range(5))
>>> g
<generator object <genexpr> at 0x10fe179e8>创建L和g的区别仅在于最外层的[]和(),L是一个list,而g是一个generator。

我们可以直接打印出list的每一个元素,但我们怎么打印出generator的每一个元素呢?
>>> for i in g:
... print(i)
...
0
1
4
9
16
>>> for i in L:
... print(i)
...
0
1
4
9
16
如果要一个一个打印出来,可以通过next()函数获得generator的下一个返回值:
>>> g = (x * x for x in range(5))
>>> next(g)
0
>>> next(g)
1
>>> next(g)
4
>>> next(g)
9
>>> next(g)
16
>>> next(g)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration

# 取完之后就会报错,因为取完了,就没有,异常关键字:StopIterationgenerator保存的是算法,每次调用next(g),就计算出g的下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出StopIteration的错误。

generator也是可迭代对象,所以,我们创建了一个generator后,基本上永远不会调用next(),而是通过for循环来迭代它,并且不需要关心StopIteration的错误。
 
generator非常强大。如果推算的算法比较复杂,用类似列表生成式的for循环无法实现的时候,还可以用函数来实现。

比如,著名的斐波拉契数列(Fibonacci),除第一个和第二个数外,任意一个数都可由前两个数相加得到:
1, 1, 2, 3, 5, 8, 13, 21, 34, ...
斐波拉契数列用列表生成式写不出来,但是,用函数把它打印出来却很容易:def fib(max):
n, a, b = 0, 0, 1
while n < max:
print(b)
a, b = b, a + b
n = n + 1
return 'done'注意,赋值语句:a, b = b, a + b相当于:
t = (b, a + b) # t是一个tuple
a = t[0]
b = t[1]但不必显式写出临时变量t就可以赋值。

上面的函数可以输出斐波那契数列的前N个数:
>>> fib(10)
1
1
2
3
5
8
13
21
34
55
done仔细观察,可以看出,fib函数实际上是定义了斐波拉契数列的推算规则,可以从第一个元素开始,推算出后续任意的元素,这种逻辑其实非常类似generator。

也就是说,上面的函数和generator仅一步之遥。要把fib函数变成generator,只需要把print(b)改为yield b就可以了:
def fib(max):
n,a,b = 0,0,1

while n < max:
#print(b)
yield b
a,b = b,a+b

n += 1

return 'done' 这就是定义generator的另一种方法。如果一个函数定义中包含yield关键字,那么这个函数就不再是一个普通函数,而是一个generator:
>>> f = fib(6)
>>> f
<generator object fib at 0x104feaaa0>这里,最难理解的就是generator和函数的执行流程不一样。函数是顺序执行,遇到return语句或者最后一行函数语句就返回。而变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。
data = fib(10)
print(data)

print(data.__next__())
print(data.__next__())
print("干点别的事")
print(data.__next__())
print(data.__next__())
print(data.__next__())
print(data.__next__())
print(data.__next__())

#输出
<generator object fib at 0x101be02b0>
1
1
干点别的事
2
3
5
8
13在上面fib的例子,我们在循环过程中不断调用yield,就会不断中断。当然要给循环设置一个条件来退出循环,不然就会产生一个无限数列出来。

同样的,把函数改成generator后,我们基本上从来不会用next()来获取下一个返回值,而是直接使用for循环来迭代:
 
>>> for n in fib(6):
... print(n)
...
1
1
2
3
5
8但是用for循环调用generator时,发现拿不到generator的return语句的返回值。如果想要拿到返回值,必须捕获StopIteration错误,返回值包含在StopIteration的value中:
>>> g = fib(6)
>>> while True:
... try:
... x = next(g)
... print('g:', x)
... except StopIteration as e:
... print('Generator return value:', e.value)
... break
...
g: 1
g: 1
g: 2
g: 3
g: 5
g: 8
Generator return value: done关于如何捕获错误,后面的错误处理还会详细讲解。

还可通过yield实现在单线程的情况下实现并发运算的效果
import time
def consumer(name):
print("%s 准备吃包子啦!" %name)
while True:
baozi = yield

print("包子[%s]来了,被[%s]吃了!" %(baozi,name))


def producer(name):
c = consumer('A')
c2 = consumer('B')
c.__next__()
c2.__next__()
print("开始准备做包子啦!")
for i in range(10):
time.sleep(1)
print("做了2个包子!")
c.send(i)
c2.send(i)

producer("lucky")

迭代器

我们已经知道,可以直接作用于for循环的数据类型有以下几种:
一类是集合数据类型,如list、tuple、dict、set、str等;一类是generator,包括生成器和带yield的generator function。这些可以直接作用于for循环的对象统称为可迭代对象:Iterable。

可以使用isinstance()判断一个对象是否是Iterable对象:
 
>>> from collections import Iterable
>>> isinstance([], Iterable)
True
>>> isinstance({}, Iterable)
True
>>> isinstance('abc', Iterable)
True
>>> isinstance((x for x in range(10)), Iterable)
True
>>> isinstance(100, Iterable)
False而生成器不但可以作用于for循环,还可以被next()函数不断调用并返回下一个值,直到最后抛出StopIteration错误表示无法继续返回下一个值了。
 
*可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator。
可以使用isinstance()判断一个对象是否是Iterator对象:
>>> from collections import Iterator
>>> isinstance((x for x in range(10)), Iterator)
True
>>> isinstance([], Iterator)
False
>>> isinstance({}, Iterator)
False
>>> isinstance('abc', Iterator)
False生成器都是Iterator对象,但list、dict、str虽然是Iterable,却不是Iterator。

把list、dict、str等Iterable变成Iterator可以使用iter()函数:
>>> isinstance(iter([]), Iterator)
True
>>> isinstance(iter('abc'), Iterator)
True你可能会问,为什么list、dict、str等数据类型不是Iterator?

这是因为Python的Iterator对象表示的是一个数据流,Iterator对象可以被next()函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration错误。可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过next()函数实现按需计算下一个数据,所以Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算。

Iterator甚至可以表示一个无限大的数据流,例如全体自然数。而使用list是永远不可能存储全体自然数的。
 
小结
凡是可作用于for循环的对象都是Iterable类型;

凡是可作用于next()函数的对象都是Iterator类型,它们表示一个惰性计算的序列;

集合数据类型如list、dict、str等是Iterable但不是Iterator,不过可以通过iter()函数获得一个Iterator对象。

Python的for循环本质上就是通过不断调用next()函数实现的,例如:
for x in [1, 2, 3, 4, 5]:
pass实际上完全等价于:
# 首先获得Iterator对象:
it = iter([1, 2, 3, 4, 5])
# 循环:
while True:
try:
# 获得下一个值:
x = next(it)
except StopIteration:
# 遇到StopIteration就退出循环
break 查看全部


生成器


通过列表生成式,我们可以直接创建一个列表。但是,受到内存限制,列表容量肯定是有限的。而且,创建一个包含100万个元素的列表,不仅占用很大的存储空间,如果我们仅仅需要访问前面几个元素,那后面绝大多数元素占用的空间都白白浪费了。
 
 
所以,如果列表元素可以按照某种算法推算出来,那我们是否可以在循环的过程中不断推算出后续的元素呢?这样就不必创建完整的list,从而节省大量的空间。在Python中,这种一边循环一边计算的机制,称为生成器:generator。
 
 
要创建一个generator,有很多种方法。第一种方法很简单,只要把一个列表生成式的[]改成(),就创建了一个generator:
>>> L = [x * x for x in range(5)]
>>> L
[0, 1, 4, 9, 16]
>>> g = (x * x for x in range(5))
>>> g
<generator object <genexpr> at 0x10fe179e8>
创建L和g的区别仅在于最外层的[]和(),L是一个list,而g是一个generator。

我们可以直接打印出list的每一个元素,但我们怎么打印出generator的每一个元素呢?
>>> for i in g:
... print(i)
...
0
1
4
9
16
>>> for i in L:
... print(i)
...
0
1
4
9
16

如果要一个一个打印出来,可以通过next()函数获得generator的下一个返回值:
>>> g = (x * x for x in range(5))
>>> next(g)
0
>>> next(g)
1
>>> next(g)
4
>>> next(g)
9
>>> next(g)
16
>>> next(g)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration

# 取完之后就会报错,因为取完了,就没有,异常关键字:StopIteration
generator保存的是算法,每次调用next(g),就计算出g的下一个元素的值,直到计算到最后一个元素,没有更多的元素时,抛出StopIteration的错误。

generator也是可迭代对象,所以,我们创建了一个generator后,基本上永远不会调用next(),而是通过for循环来迭代它,并且不需要关心StopIteration的错误。
 
generator非常强大。如果推算的算法比较复杂,用类似列表生成式的for循环无法实现的时候,还可以用函数来实现。

比如,著名的斐波拉契数列(Fibonacci),除第一个和第二个数外,任意一个数都可由前两个数相加得到:
1, 1, 2, 3, 5, 8, 13, 21, 34, ...
斐波拉契数列用列表生成式写不出来,但是,用函数把它打印出来却很容易:
def fib(max):
n, a, b = 0, 0, 1
while n < max:
print(b)
a, b = b, a + b
n = n + 1
return 'done'
注意,赋值语句:
a, b = b, a + b
相当于:
t = (b, a + b) # t是一个tuple
a = t[0]
b = t[1]
但不必显式写出临时变量t就可以赋值。

上面的函数可以输出斐波那契数列的前N个数:
>>> fib(10)
1
1
2
3
5
8
13
21
34
55
done
仔细观察,可以看出,fib函数实际上是定义了斐波拉契数列的推算规则,可以从第一个元素开始,推算出后续任意的元素,这种逻辑其实非常类似generator。

也就是说,上面的函数和generator仅一步之遥。要把fib函数变成generator,只需要把print(b)改为yield b就可以了:
def fib(max):
n,a,b = 0,0,1

while n < max:
#print(b)
yield b
a,b = b,a+b

n += 1

return 'done'
这就是定义generator的另一种方法。如果一个函数定义中包含yield关键字,那么这个函数就不再是一个普通函数,而是一个generator:
>>> f = fib(6)
>>> f
<generator object fib at 0x104feaaa0>
这里,最难理解的就是generator和函数的执行流程不一样。函数是顺序执行,遇到return语句或者最后一行函数语句就返回。而变成generator的函数,在每次调用next()的时候执行,遇到yield语句返回,再次执行时从上次返回的yield语句处继续执行。
data = fib(10)
print(data)

print(data.__next__())
print(data.__next__())
print("干点别的事")
print(data.__next__())
print(data.__next__())
print(data.__next__())
print(data.__next__())
print(data.__next__())

#输出
<generator object fib at 0x101be02b0>
1
1
干点别的事
2
3
5
8
13
在上面fib的例子,我们在循环过程中不断调用yield,就会不断中断。当然要给循环设置一个条件来退出循环,不然就会产生一个无限数列出来。

同样的,把函数改成generator后,我们基本上从来不会用next()来获取下一个返回值,而是直接使用for循环来迭代:
 
>>> for n in fib(6):
... print(n)
...
1
1
2
3
5
8
但是用for循环调用generator时,发现拿不到generator的return语句的返回值。如果想要拿到返回值,必须捕获StopIteration错误,返回值包含在StopIteration的value中:
>>> g = fib(6)
>>> while True:
... try:
... x = next(g)
... print('g:', x)
... except StopIteration as e:
... print('Generator return value:', e.value)
... break
...
g: 1
g: 1
g: 2
g: 3
g: 5
g: 8
Generator return value: done
关于如何捕获错误,后面的错误处理还会详细讲解。

还可通过yield实现在单线程的情况下实现并发运算的效果
import time
def consumer(name):
print("%s 准备吃包子啦!" %name)
while True:
baozi = yield

print("包子[%s]来了,被[%s]吃了!" %(baozi,name))


def producer(name):
c = consumer('A')
c2 = consumer('B')
c.__next__()
c2.__next__()
print("开始准备做包子啦!")
for i in range(10):
time.sleep(1)
print("做了2个包子!")
c.send(i)
c2.send(i)

producer("lucky")


迭代器


我们已经知道,可以直接作用于for循环的数据类型有以下几种:
  • 一类是集合数据类型,如list、tuple、dict、set、str等;
  • 一类是generator,包括生成器和带yield的generator function。
  • 这些可以直接作用于for循环的对象统称为可迭代对象:Iterable。


可以使用isinstance()判断一个对象是否是Iterable对象:
 
>>> from collections import Iterable
>>> isinstance([], Iterable)
True
>>> isinstance({}, Iterable)
True
>>> isinstance('abc', Iterable)
True
>>> isinstance((x for x in range(10)), Iterable)
True
>>> isinstance(100, Iterable)
False
而生成器不但可以作用于for循环,还可以被next()函数不断调用并返回下一个值,直到最后抛出StopIteration错误表示无法继续返回下一个值了。
 
*可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator。
可以使用isinstance()判断一个对象是否是Iterator对象:
>>> from collections import Iterator
>>> isinstance((x for x in range(10)), Iterator)
True
>>> isinstance([], Iterator)
False
>>> isinstance({}, Iterator)
False
>>> isinstance('abc', Iterator)
False
生成器都是Iterator对象,但list、dict、str虽然是Iterable,却不是Iterator。

把list、dict、str等Iterable变成Iterator可以使用iter()函数:
>>> isinstance(iter([]), Iterator)
True
>>> isinstance(iter('abc'), Iterator)
True
你可能会问,为什么list、dict、str等数据类型不是Iterator?

这是因为Python的Iterator对象表示的是一个数据流,Iterator对象可以被next()函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration错误。可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过next()函数实现按需计算下一个数据,所以Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算。

Iterator甚至可以表示一个无限大的数据流,例如全体自然数。而使用list是永远不可能存储全体自然数的。
 
小结
凡是可作用于for循环的对象都是Iterable类型;

凡是可作用于next()函数的对象都是Iterator类型,它们表示一个惰性计算的序列;

集合数据类型如list、dict、str等是Iterable但不是Iterator,不过可以通过iter()函数获得一个Iterator对象。

Python的for循环本质上就是通过不断调用next()函数实现的,例如:
for x in [1, 2, 3, 4, 5]:
pass
实际上完全等价于:
# 首先获得Iterator对象:
it = iter([1, 2, 3, 4, 5])
# 循环:
while True:
try:
# 获得下一个值:
x = next(it)
except StopIteration:
# 遇到StopIteration就退出循环
break

Python3内置函数介绍

编程语言采菊篱下 发表了文章 • 0 个评论 • 90 次浏览 • 2016-08-19 17:28 • 来自相关话题

详情参考:https://docs.python.org/3/library/functions.html​ 
 
1、abs(x)(返回一个数的绝对值)
>>> abs(-12)
12
>>> abs(-12.89)
12.89
>>> abs(-0.1)
0.1 
2、all(iterable) 
all会循环括号内的每一个元素,如果括号内的所有元素都是真的,则返回True,如果有一个为假的那么就返回False
>>> all([0, 3])
False
>>> all([1, 3])
True
>>> all([1, ""])
False一假则假,假的参数有:False、0、None、""、[]、()、{}等。
查看一个元素是否为假可以使用bool进行查看:
>>> bool("")
False
>>> bool(())
False
>>> bool(0)
False
>>> bool(1)
True
3、any(iterable)
循环元素,如果有一个元素为真,那么就返回真,一真则真。
>>> any([0, 1, 2, 3])
True
>>> any([{}, (), 0])
False
4、ascii(object)
在对象的类中寻找__repr__方法,获取返回值
 
 
>>> class Foo:
... def __repr_(self):
... return "Result"
...
>>> obj = Foo()
>>> r = ascii(obj)
>>> print(r)
<__main__.Foo object at 0x1045075c0>
5、bin(x)
将整数x转换为二进制字符串,如果x不为Python中int类型,x必须包含方法index()并且返回值为integer
 
# 返回一个整数的二进制
>>> bin(999)
'0b1111100111'# 非整型的情况,必须包含__index__()方法切返回值为integer的类型
>>> class myType:
... def __index__(self):
... return 35
...
>>> myvar = myType()
>>> bin(myvar)
'0b100011'
6、bool([x])
查看一个元素的布尔值,非真即假
>>> bool([])
False
>>> bool(0)
False
>>> bool(1)
True
7、bytearray([source [, encoding [, errors]]])
bytearray([source [, encoding [, errors]]])返回一个byte数组。Bytearray类型是一个可变的序列,并且序列中的元素的取值范围为 [0 ,255]。
 
source参数:
如果source为整数,则返回一个长度为source的初始化数组;如果source为字符串,则按照指定的encoding将字符串转换为字节序列;如果source为可迭代类型,则元素必须为[0 ,255]中的整数;如果source为与buffer接口一致的对象,则此对象也可以被用于初始化bytearray。
 
>>> bytearray(3)
bytearray(b'\x00\x00\x00')
8、bytes([source[, encoding[, errors]]])
>>> bytes("asdasd",encoding="utf-8")
b'asdasd'返回一个bytes类型。
 
9、callable(object)
返回一个对象是否可以被执行
 
>>> def func():
... return 123
...
>>> callable(func)
True
>>> func = 123
>>> callable(func)
False
10、chr(i)
返回一个数字在ASCII编码中对应的字符,取值范围256个
>>> chr(66)
'B'
>>> chr(5)
'\x05'
>>> chr(55)
'7'
>>> chr(255)
'\xff'
>>> chr(25)
'\x19'
>>> chr(65)
'A'
11、compile(source, filename, mode, flags=0, dont_inherit=False, optimize=-1)
把字符串编译成python可执行的代码
 
>>> str = "for i in range(0,6): print(i)"
>>> c = compile(str, '', 'exec')
>>> exec(c)
0
1
2
3
4
5
 
12、complex([real[, imag]])
创建一个值为real + imag * j的复数或者转化一个字符串或数为复数。如果第一个参数为字符串,则不需要指定第二个参数
>>> complex(1, 2)
(1+2j)
# 数字
>>> complex(1)
(1+0j)
# 当做字符串处理
>>> complex("1")
(1+0j)
# 注意:这个地方在“+”号两边不能有空格,也就是不能写成"1 + 2j",应该是"1+2j",否则会报错
>>> complex("1+2j")
(1+2j)
13、dict(**kwarg)
创建一个数据类型为字典
 
>>> dic = dict({"k1":"123","k2":"456"})
>>> dic
{'k1': '123', 'k2': '456'}
14、dir([object])
返回一个类中的所有方法
 
>>> a = [1, 2, 3, 4]
>>> dir(a)
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
15、divmod(a, b)
divmod(a,b)方法返回的是a//b(除法取整)以及a对b的余数,返回结果类型为tuple
 
 
>>> divmod(10, 3)
(3, 1)
16、enumerate(iterable, start=0)
遍历可迭代的数据类型,为元素生成下标
>>> a = [0, 1, 2, 3]
>>> for n, k in enumerate(a):
... print(n, k)
...
0 0
1 1
2 2
3 3
17、eval(expression, globals=None, locals=None)
把一个字符串当作一个表达式去执行
>>> string = "1 + 3"
>>> string
'1 + 3'
>>> eval(string)
4

 
18、exec(object[, globals[, locals]])
把字符串当作python代码执行
>>> exec("for n in range(5): print(n)")
0
1
2
3
4
19、filter(function, iterable)
筛选过滤,循环可迭代的对象,把迭代的对象当作函数的参数,如果符合条件就返回True,否则就返回False
>>> def func(x):
... if x == 11 or x == 22:
... return True
...
>>> ret = filter(func,[11,22,33,44])
>>> for n in ret:
... print(n)
...
11
22
20、float([x])
将整数和字符串转换成浮点数
>>> float("124")
124.0
>>> float("123.45")
123.45
>>> float("-123.34")
-123.34

 
21、format(value[, format_spec]) 
字符串格式化
>>> a = "My name is {0}, age is {1}".format('lucky', 18)
>>> print(a)
My name is lucky, age is 18
22、frozenset([iterable])
frozenset是冻结的集合,它是不可变的,存在哈希值,好处是它可以作为字典的key,也可以作为其它集合的元素。缺点是一旦创建便不能更改,没有add,remove方法。
 
23、globals()
获取当前scripts文件内的所有全局变量
 
>>> a = 3
>>> bsd = "54asd"
>>> globals()
{'__doc__': None, 'bsd': '54asd', '__package__': None, 'a': 3, '__spec__': None, '__builtins__': <module 'builtins' (built-in)>, '__name__': '__main__', '__loader__': <class '_frozen_importlib.BuiltinImporter'>}
24、hash(object)
返回一个对象的hash值
 
>>> a = "asdadasdwqeq234sdfdf"
>>> hash(a)
5390438057823015497
25、help([object])
查看一个类的所有详细方法
 
>>> help(list)
Help on class list in module __builtin__:

class list(object)
| list() -> new empty list
| list(iterable) -> new list initialized from iterable's items
|
| Methods defined here:
|
| __add__(...)
| x.__add__(y) <==> x+y
|
| __contains__(...)
| x.__contains__(y) <==> y in x
|
| __delitem__(...)
| x.__delitem__(y) <==> del x[y]
|
| __delslice__(...)
| x.__delslice__(i, j) <==> del x[i:j]
|
| Use of negative indices is not supported.
..........
26、hex(x)
获取一个数的十六进制
 
>>> hex(13)
'0xd'
27、id(object)
返回一个对象的内存地址
>>> a = 123
>>> id(a)
1835400816
28、input([prompt])
交互式输入
 
 
29、int(x, base=10)
获取一个数的十进制
>>> int("31")
31
30、isinstance(object, classinfo)
判断对象是否是这个类创建的
 
>>> li = [11,22,33]
>>> isinstance(li,list)
True
31、issubclass(class, classinfo)
查看一个对象是否为子类
 
32、iter(object[, sentinel])
创建一个可迭代的对象
>>> obj = iter([11,22,33,44])
>>> obj
<list_iterator object at 0x000002477DB25198>
>>> for n in obj:
... print(n)
...
11
22
33
44

 
33、len(s)
查看一个对象的长度
 
>>> name = 'lucky'
>>> len(name)
5
34、list([iterable])
创建一个数据类型为列表
>>> li = list([11,22,33,44])
>>> li
[11, 22, 33, 44]
35、locals()
返回当前scripts的局部变量,返回结果为字典格式
>>> def func():
... name="lucky"
... print(locals())
...
>>> func()
{'name': 'lucky'}
 
 
36、map(function, iterable, …)
把可迭代的对象作为函数的值
 
>>> ret = map(lambda x: x + 100, [1, 2, 3, 4, 5])
>>> for n in ret:
... print(n)
...
101
102
103
104
105
37、max(iterable, *[, key, default]) max(arg1, arg2, *args[, key])
获取一个对象中的最大值
 
>>> li = [1, 3, 5, 9 ,3]
>>> max(li)
9
38、min(iterable, *[, key, default])  min(arg1, arg2, *args[, key])
获取一个对象中的最小值
>>> li = list([11,22,33,44])
>>> li = [11,22,33,44]
>>> min(li)
11
39、next(iterator[, default])
 
每次只拿取可迭代对象的一个元素
 
>>> obj = iter([11,22,33,44])
>>> next(obj)
11
>>> next(obj)
22
>>> next(obj)
33
>>> next(obj)
44
>>> next(obj)
# 如果没有可迭代的元素了就会报错
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
40、oct(x)
获取一个字符串的八进制
>>> oct(13)
'0o15'
41、open(file, mode=’r’, buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
文件操作的函数,用来做文件操作的
 
 
 
42、ord(c)
把一个字母转换为ASCII对对应表中的数字
 
>>> ord("a")
97
>>> ord("t")
116
43、pow(x, y[, z])
返回一个数的N次方
>>> pow(2, 10)
1024
>>> pow(2, 20)
1048576
 
44、print(*objects, sep=’ ‘, end=’\n’, file=sys.stdout, flush=False)
打印输出
 
 
45、range(start, stop[, step])
生成一个可迭代序列
 
>>> range(10)
range(0, 10)
>>> for n in range(5):
... print(n)
...
0
1
2
3
4
46、reversed(seq)
对一个对象的元素进行反转
>>> li = [1, 2, 3, 4]
>>> reversed(li)
<list_reverseiterator object at 0x000002CF0EF6A940>
>>> for n in reversed(li):
... print(n)
...
4
3
2
1
47、round(number[, ndigits])
四舍五入
>>> round(3.3)
3
>>> round(3.7)
4
48、set([iterable])
创建一个数据类型为集合
>>> varss = set([11,222,333])
>>> type(varss)
<class 'set'>
49、slice(start, stop[, step])
元素的切片操作都是调用的这个方法
 
50、sorted(iterable[, key][, reverse])
为一个对象的元素进行排序
 
>>> li = [ 2, 3, 4, 9, 1, 100]
>>> sorted(li)
[1, 2, 3, 4, 9, 100]
51、sum(iterable[, start])
求和
>>> sum([11,22,33])
66
52、type(object)
查看一个对象的数据类型
 
>>> a = 1
>>> type(a)
<class 'int'>
>>> a = "str"
>>> type(a)
<class 'str'>
53、vars([object])
查看一个对象里面有多少个变量
 
54、zip(*iterables)
联合迭代
>>> li1 = ["k1","k2","k3"]
>>> li2 = ["a","b","c"]
>>> zip(li1,li2)
<zip object at 0x0000026BF1803288>
>>> dic = zip(li1,li2)
>>> for n in dic:
... print(n)
...
('k1', 'a')
('k2', 'b')
('k3', 'c')
55、import(name, globals=None, locals=None, fromlist=(), level=0)
导入模块,把导入的模块作为一个别名。
生成一个六位的随机验证码,且包含数字,数字的位置随机:
# 导入random模块
import random
temp = ""
for i in range(6):
num = random.randrange(0,4)
if num == 3 or num == 1:
rad2 = random.randrange(0,10)
temp = temp + str(rad2)
else:
rad1 = random.randrange(65,91)
c1 = chr(rad1)
temp = temp + c1
print(temp) 查看全部
intfunc.png

详情参考:https://docs.python.org/3/library/functions.html​ 
 
1、abs(x)(返回一个数的绝对值)
>>> abs(-12)
12
>>> abs(-12.89)
12.89
>>> abs(-0.1)
0.1
 
2、all(iterable) 
all会循环括号内的每一个元素,如果括号内的所有元素都是真的,则返回True,如果有一个为假的那么就返回False
>>> all([0, 3])
False
>>> all([1, 3])
True
>>> all([1, ""])
False
一假则假,假的参数有:False、0、None、""、[]、()、{}等。
查看一个元素是否为假可以使用bool进行查看:
>>> bool("")
False
>>> bool(())
False
>>> bool(0)
False
>>> bool(1)
True

3、any(iterable)
循环元素,如果有一个元素为真,那么就返回真,一真则真。
>>> any([0, 1, 2, 3])
True
>>> any([{}, (), 0])
False

4、ascii(object)
在对象的类中寻找__repr__方法,获取返回值
 
 
>>> class Foo:
... def __repr_(self):
... return "Result"
...
>>> obj = Foo()
>>> r = ascii(obj)
>>> print(r)
<__main__.Foo object at 0x1045075c0>

5、bin(x)
将整数x转换为二进制字符串,如果x不为Python中int类型,x必须包含方法index()并且返回值为integer
 
# 返回一个整数的二进制
>>> bin(999)
'0b1111100111'
# 非整型的情况,必须包含__index__()方法切返回值为integer的类型
>>> class myType:
... def __index__(self):
... return 35
...
>>> myvar = myType()
>>> bin(myvar)
'0b100011'

6、bool([x])
查看一个元素的布尔值,非真即假
>>> bool([])
False
>>> bool(0)
False
>>> bool(1)
True

7、bytearray([source [, encoding [, errors]]])
bytearray([source [, encoding [, errors]]])返回一个byte数组。Bytearray类型是一个可变的序列,并且序列中的元素的取值范围为 [0 ,255]。
 
source参数:
  • 如果source为整数,则返回一个长度为source的初始化数组;
  • 如果source为字符串,则按照指定的encoding将字符串转换为字节序列;
  • 如果source为可迭代类型,则元素必须为[0 ,255]中的整数;
  • 如果source为与buffer接口一致的对象,则此对象也可以被用于初始化bytearray。

 
>>> bytearray(3)
bytearray(b'\x00\x00\x00')

8、bytes([source[, encoding[, errors]]])
>>> bytes("asdasd",encoding="utf-8")
b'asdasd'
返回一个bytes类型。
 
9、callable(object)
返回一个对象是否可以被执行
 
>>> def func():
... return 123
...
>>> callable(func)
True
>>> func = 123
>>> callable(func)
False

10、chr(i)
返回一个数字在ASCII编码中对应的字符,取值范围256个
>>> chr(66)
'B'
>>> chr(5)
'\x05'
>>> chr(55)
'7'
>>> chr(255)
'\xff'
>>> chr(25)
'\x19'
>>> chr(65)
'A'

11、compile(source, filename, mode, flags=0, dont_inherit=False, optimize=-1)
把字符串编译成python可执行的代码
 
>>> str = "for i in range(0,6): print(i)"
>>> c = compile(str, '', 'exec')
>>> exec(c)
0
1
2
3
4
5

 
12、complex([real[, imag]])
创建一个值为real + imag * j的复数或者转化一个字符串或数为复数。如果第一个参数为字符串,则不需要指定第二个参数
>>> complex(1, 2)
(1+2j)
# 数字
>>> complex(1)
(1+0j)
# 当做字符串处理
>>> complex("1")
(1+0j)
# 注意:这个地方在“+”号两边不能有空格,也就是不能写成"1 + 2j",应该是"1+2j",否则会报错
>>> complex("1+2j")
(1+2j)

13、dict(**kwarg)
创建一个数据类型为字典
 
>>> dic = dict({"k1":"123","k2":"456"})
>>> dic
{'k1': '123', 'k2': '456'}

14、dir([object])
返回一个类中的所有方法
 
>>> a = [1, 2, 3, 4]
>>> dir(a)
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']

15、divmod(a, b)
divmod(a,b)方法返回的是a//b(除法取整)以及a对b的余数,返回结果类型为tuple
 
 
>>> divmod(10, 3)
(3, 1)

16、enumerate(iterable, start=0)
遍历可迭代的数据类型,为元素生成下标
>>> a = [0, 1, 2, 3]
>>> for n, k in enumerate(a):
... print(n, k)
...
0 0
1 1
2 2
3 3

17、eval(expression, globals=None, locals=None)
把一个字符串当作一个表达式去执行
>>> string = "1 + 3"
>>> string
'1 + 3'
>>> eval(string)
4

 
18、exec(object[, globals[, locals]])
把字符串当作python代码执行
>>> exec("for n in range(5): print(n)")
0
1
2
3
4

19、filter(function, iterable)
筛选过滤,循环可迭代的对象,把迭代的对象当作函数的参数,如果符合条件就返回True,否则就返回False
>>> def func(x):
... if x == 11 or x == 22:
... return True
...
>>> ret = filter(func,[11,22,33,44])
>>> for n in ret:
... print(n)
...
11
22

20、float([x])
将整数和字符串转换成浮点数
>>> float("124")
124.0
>>> float("123.45")
123.45
>>> float("-123.34")
-123.34

 
21、format(value[, format_spec]) 
字符串格式化
>>> a = "My name is {0}, age is {1}".format('lucky', 18)
>>> print(a)
My name is lucky, age is 18

22、frozenset([iterable])
frozenset是冻结的集合,它是不可变的,存在哈希值,好处是它可以作为字典的key,也可以作为其它集合的元素。缺点是一旦创建便不能更改,没有add,remove方法。
 
23、globals()
获取当前scripts文件内的所有全局变量
 
>>> a = 3
>>> bsd = "54asd"
>>> globals()
{'__doc__': None, 'bsd': '54asd', '__package__': None, 'a': 3, '__spec__': None, '__builtins__': <module 'builtins' (built-in)>, '__name__': '__main__', '__loader__': <class '_frozen_importlib.BuiltinImporter'>}

24、hash(object)
返回一个对象的hash值
 
>>> a = "asdadasdwqeq234sdfdf"
>>> hash(a)
5390438057823015497

25、help([object])
查看一个类的所有详细方法
 
>>> help(list)
Help on class list in module __builtin__:

class list(object)
| list() -> new empty list
| list(iterable) -> new list initialized from iterable's items
|
| Methods defined here:
|
| __add__(...)
| x.__add__(y) <==> x+y
|
| __contains__(...)
| x.__contains__(y) <==> y in x
|
| __delitem__(...)
| x.__delitem__(y) <==> del x[y]
|
| __delslice__(...)
| x.__delslice__(i, j) <==> del x[i:j]
|
| Use of negative indices is not supported.
..........

26、hex(x)
获取一个数的十六进制
 
>>> hex(13)
'0xd'

27、id(object)
返回一个对象的内存地址
>>> a = 123
>>> id(a)
1835400816

28、input([prompt])
交互式输入
 
 
29、int(x, base=10)
获取一个数的十进制
>>> int("31")
31

30、isinstance(object, classinfo)
判断对象是否是这个类创建的
 
>>> li = [11,22,33]
>>> isinstance(li,list)
True

31、issubclass(class, classinfo)
查看一个对象是否为子类
 
32、iter(object[, sentinel])
创建一个可迭代的对象
>>> obj = iter([11,22,33,44])
>>> obj
<list_iterator object at 0x000002477DB25198>
>>> for n in obj:
... print(n)
...
11
22
33
44

 
33、len(s)
查看一个对象的长度
 
>>> name = 'lucky'
>>> len(name)
5

34、list([iterable])
创建一个数据类型为列表
>>> li = list([11,22,33,44])
>>> li
[11, 22, 33, 44]

35、locals()
返回当前scripts的局部变量,返回结果为字典格式
>>> def func():
... name="lucky"
... print(locals())
...
>>> func()
{'name': 'lucky'}

 
 
36、map(function, iterable, …)
把可迭代的对象作为函数的值
 
>>> ret = map(lambda x: x + 100, [1, 2, 3, 4, 5])
>>> for n in ret:
... print(n)
...
101
102
103
104
105

37、max(iterable, *[, key, default]) max(arg1, arg2, *args[, key])
获取一个对象中的最大值
 
>>> li = [1, 3, 5, 9 ,3]
>>> max(li)
9

38、min(iterable, *[, key, default])  min(arg1, arg2, *args[, key])
获取一个对象中的最小值
>>> li = list([11,22,33,44])
>>> li = [11,22,33,44]
>>> min(li)
11

39、next(iterator[, default])
 
每次只拿取可迭代对象的一个元素
 
>>> obj = iter([11,22,33,44])
>>> next(obj)
11
>>> next(obj)
22
>>> next(obj)
33
>>> next(obj)
44
>>> next(obj)
# 如果没有可迭代的元素了就会报错
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration

40、oct(x)
获取一个字符串的八进制
>>> oct(13)
'0o15'

41、open(file, mode=’r’, buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None)
文件操作的函数,用来做文件操作的
 
 
 
42、ord(c)
把一个字母转换为ASCII对对应表中的数字
 
>>> ord("a")
97
>>> ord("t")
116

43、pow(x, y[, z])
返回一个数的N次方
>>> pow(2, 10)
1024
>>> pow(2, 20)
1048576

 
44、print(*objects, sep=’ ‘, end=’\n’, file=sys.stdout, flush=False)
打印输出
 
 
45、range(start, stop[, step])
生成一个可迭代序列
 
>>> range(10)
range(0, 10)
>>> for n in range(5):
... print(n)
...
0
1
2
3
4

46、reversed(seq)
对一个对象的元素进行反转
>>> li = [1, 2, 3, 4]
>>> reversed(li)
<list_reverseiterator object at 0x000002CF0EF6A940>
>>> for n in reversed(li):
... print(n)
...
4
3
2
1

47、round(number[, ndigits])
四舍五入
>>> round(3.3)
3
>>> round(3.7)
4

48、set([iterable])
创建一个数据类型为集合
>>> varss = set([11,222,333])
>>> type(varss)
<class 'set'>

49、slice(start, stop[, step])
元素的切片操作都是调用的这个方法
 
50、sorted(iterable[, key][, reverse])
为一个对象的元素进行排序
 
>>> li = [ 2, 3, 4, 9, 1, 100]
>>> sorted(li)
[1, 2, 3, 4, 9, 100]

51、sum(iterable[, start])
求和
>>> sum([11,22,33])
66

52、type(object)
查看一个对象的数据类型
 
>>> a = 1
>>> type(a)
<class 'int'>
>>> a = "str"
>>> type(a)
<class 'str'>

53、vars([object])
查看一个对象里面有多少个变量
 
54、zip(*iterables)
联合迭代
>>> li1 = ["k1","k2","k3"]
>>> li2 = ["a","b","c"]
>>> zip(li1,li2)
<zip object at 0x0000026BF1803288>
>>> dic = zip(li1,li2)
>>> for n in dic:
... print(n)
...
('k1', 'a')
('k2', 'b')
('k3', 'c')

55、import(name, globals=None, locals=None, fromlist=(), level=0)
导入模块,把导入的模块作为一个别名。
生成一个六位的随机验证码,且包含数字,数字的位置随机:
# 导入random模块
import random
temp = ""
for i in range(6):
num = random.randrange(0,4)
if num == 3 or num == 1:
rad2 = random.randrange(0,10)
temp = temp + str(rad2)
else:
rad1 = random.randrange(65,91)
c1 = chr(rad1)
temp = temp + c1
print(temp)