Python的标准logging模块

0
挖一下

Python 2.3 introduced the logging module to the Python standard library. logging provides a standard interface for outputting information from a running application. The classic example of a logging mechanism is writing data to a text file, which is a plain old log file. While the log file is likely the most common form of logging, the logging module provides the ability to send information to file-like objects, TCP and UDP sockets, email servers, the Unix syslog, the NT event log, memory buffers, and HTTP servers in addition to “real” files.

从Python2.3起,Python的标准库加入了logging模块.logging模块给运行中的应用 提供了一个标准的信息输出接口.典型的logging机制实现是把要输出的数据简单地写到一个txt文件中去.写log文件的方式是一种常见的打log的 方式,而logging模块提供的更多,它可以把输出信息输出到所有类文件的对象中去,甚至TCP和UDP的sockets,email服务器,Unix 的syslog系统,NT系列的事件log系统,内存的buffer和HTTP服务器,当然还有”真正的”文件中去.

The logging library takes a modular approach and offers the several categories of components: loggers, handlers, filters, and formatters. Loggers expose the interface that application code directly uses. Handlers send the log records to the appropriate destination. Filters provide a finer grained facility for determining which log records to send on to a handler. Formatters specify the layout of the resultant log record.

Logging库被设计成模块的方式,它提供了以下几个子模 块:loggers,handlers,filters和formatters.Loggers把应用需要直接调用的接口暴露出来.Handlers把 log记录发到相应的目的地.Filters决定哪些记录需要发给handler.Formatters定义了log记录的输出格式.

Loggers

Logger objects have a threefold job. First, they expose several methods to application code so that applications can log messages at runtime. Second, logger objects determine which log messages to act upon based upon severity (the default filtering facility) or filter objects. Third, logger objects pass along relevant log messages to all interested log handlers.

Logger对象扮演了三重角色.首先,它暴露给应用几个方法以便应用可以在运行时写 log.其次,Logger对象按照log信息的严重程度或者根据filter对象来决定如何处理log信息(默认的过滤功能).最后,logger还负 责把log信息传送给相关的loghandlers.

The most widely used methods on logger objects fall into two categories: configuration and message sending.

Logger中最长使用的方法分成两部分中:configuration和message sending.

The configuration methods are:

用于Configuration的方法:

* setLevel(level)
* addFilter(filter)
* removeFilter(filter)
* addHandler(handler)
* removeHandler(handler)

setLevel() specifies the lowest-severity log message a logger will handle, where debug is the lowest built-in severity level and critical is the highest built-in severity. For example, if the severity level is info, the logger will handle only info, warning, error, and critical messages and will ignore debug messages.

addFilter() and removeFilter() add and remove filter objects from the logger object. This article does not address filters.

setLevel() 方法定义了一个logger处理的最底严重程度(比如说中/高/底三种,我定义为中,那么只有严重程度为中或者高的log才会被处理).debug级别是 内置的最低级别,critical是最高级别.举例来说,如果严重级别设为info级,logger仅仅处理info,warning,error和 critical级的log,而debug级别的则忽略掉.

With the logger object configured, the following methods create log messages:

根据logger对象的设置,以下的方法被用来写log:

* debug(log_message, [*args[, **kwargs]])
* info(log_message, [*args[, **kwargs]])
* warning(log_message, [*args[, **kwargs]])
* error(log_message, [*args[, **kwargs]])
* critical(log_message, [*args[, **kwargs]])
* exception(message[, *args])
* log(log_level, log_message, [*args[, **kwargs]])

debug(), info(), warning(), error(), and critical() all create log records with a message of log_message and a level that corresponds to their respective method names. log_message is actually a format string, which may contain the standard string substitution syntax of %s, %d, %f, and so on. *args is a list of objects that correspond with the substitution fields in log_message. With regard to **kwargs, the logging methods care only about a keyword of exc_info and use it to determine whether to log exception information.

debug(),info(),warning(),error()和 critical()方法用一个log_message格式字符串和与之对应的各个参数来生成log信息.log_message实际上是一个格式字符 串,它可以包含诸如%s,%d,%f此类的替换符号.*args是实际要替换%s,%d,%f参数的列表.至于这个**kwargs关键字参 数,logging只处理一个关键字exc_info,这个关键字决定是否对异常信息打log.

exception() creates a log message similar to error(). The difference is that exception() dumps a stack trace along with it. Call this method only from an exception handler.

exception()跟error()方法基本一样.不同之处是exception()多出一个stack trace用于转储.exception()方法只能从一个exception handler里面调用.

log() takes a log level as an explicit argument. This is a little more verbose for logging messages than using the log level convenience methods listed above, but this is how to log at custom log levels.

Log()方法显式的带一个level参数,用这个可以得到比使用上面所列举的方法更为详细的log信息,这属于自定义log信息的范畴了.

logging.getLogger([name]) returns a reference to a logger instance with a name of name if a name is provided, or root if not. The names are period-separated (.) hierarchical structures. Multiple calls to logging.getLogger() with the same name will return a reference to the same logger object. Loggers that are further down in the hierarchical list are children of loggers higher up in the list. For example, given a logger with a name of foo, loggers with names of foo.bar, foo.bar.baz, and foo.bam are all children of foo. Child loggers propagate messages up to their parent loggers. Because of this, it is unnecessary to define and configure all the loggers an application uses. It is sufficient to configure a top-level logger and create child loggers as needed.

Logging.getLogger([name]) 方法返回一个logger实例的引用,如果name参数给出,则用这个参数的值作为名字,如果没有则用root做默认值.名字是以点号分割的命名方式命名 的(a.b.c).对同一个名字的多个调用logging.getLogger()方法会返回同一个logger对象.这种命名方式里面,后面的 loggers是前面logger的子.比如说,有一个名字是foo的logger,那么诸如foo.bar,foo.bar.baz和foo.bam这 样的logger都是foo这个logger的子,子loggers自动继承父loggers的log信息,正因为此,没有必要把一个应用的所有 logger都配置一边,只要把顶层的logger配置好了,然后子logger根据需要继承就行了.

Handlers

Handler objects are responsible for dispatching the appropriate log messages (based on the log messages’ severity) to the handler’s specified destination. Logger objects can add zero or more handler objects to themselves with an addHandler() method. As an example scenario, an application may want to send all log messages to a log file, all log messages of error or higher to stdout, and all messages of critical to an email address. This scenario requires three individual handlers where each hander is responsible for sending messages of a specific severity to a specific location.

Handler对象负责分配合适的log信息(基于log信息的严重 程度)到handler指定的目的地.Logger对象可以用addHandler()方法添加零个或多个handler对象到它自身.一个常见的场景 是,一个应用可能希望把所有的log信息都发送到一个log文件中去,所有的error级别以上的log信息都发送到stdout,所有critical 的log信息通过email发送.这个场景里要求三个不同handler处理,每个handler负责把特定的log信息发送到特定的地方.

The standard library includes the following handlers:

标准库里面包括以下的handlers:

* StreamHandler
* FileHandler
* RotatingFileHandler
* TimedRotatingFileHandler
* SocketHandler
* DatagramHandler
* SysLogHandler
* NTEventLogHandler
* SMTPHandler
* MemoryHandler
* HTTPHandler

This article uses only StreamHandler and FileHandler in its examples.

本文里面只用到了StreamHandler和FileHandler

There are very few methods in a handler for application developers to concern themselves with. The only handler methods that seem relevant for application developers who are using the built-in handler objects (that is, not creating custom handlers) are the following configuration methods:

Handler里面提供给应用开发者的只有很少的几个方法可用.对使用内置的handler(就是说不是自定义的handlers)的开发者可用的配置方法如下:

* setLevel(level)
* setFormatter(formatter)
* addFilter(filter)
* removeFilter(filter)

The setLevel() method, just as in logger objects, specifies the lowest severity that will be dispatched to the appropriate destination. Why are there two setLevel() methods? The level set in the logger determines which severity of messages it will pass to its handlers. The level set in each handler determines which messages that handler will send on. setFormatter() selects a Formatter object for this handler to use. addFilter() and removeFilter() respectively configure and deconfigure filter objects on handlers.

setLevel()方法跟logger对象里面的 setLevel()一样,也是用于设定一个最低分发log信息的级别.为什么有两个setLevel()呢?logger的严重等级用于决定那个级别的 log信息可以分发到它的handlers.handler里面的level设置用于控制那些个log信息是handler需要转寄 的.setFormatter()方法选定一个格式化对象给它自己用.addFilter()和removeFilter()分别用于为handler增 加一个filter和删除一个filter.

Application code should not directly instantiate and use handlers. Instead, the logging.Handler class is a base class that defines the interface that all Handlers should have and establishes some default behavior that child classes can use (or override).

应用里面Handler不应该被直接实例化.相反,应该用logging.Handler类作所有Handlers的基类,在它里面定义所有自Handler用到的接口并且创建一些默认的方法让子类来用(或者继承).

MySQL5之视图、索引

0
挖一下

使用“视图”的目的:

1. 重用SQL语句

2. 简化复杂的SQL操作

3. 为了只是暴露部分的表

4. 为了数据的安全

5. 为了改变数据的格式和表现形式

但是,由于视图不包括任何数据,因此每次调用它都需要执行一连串的sql请求,性能上也许要等待一段时间)

# 案例背景(获取已经购买了某个产品的客户的姓名、联系人)

SELECT cust_name, cust_contact

FROM customers, orders, orderitems

WHERE customers.cust_id = orders.cust_id

AND orderitems.order_num = orders.order_num

AND prod_id = ‘TNT2′;

# 如果还有别的人想要获得“获取已经购买了某个产品的客户的姓名、联系人”

# 那么其他人还需要知道这个table的结构,知道怎么创建查询和联系表

# 如果需要获得其他产品的信息,还需要修改 where 条款

# 针对上面的不便之处,可以创建一个“视图”来帮助

CREATE VIEW productcustomers AS

SELECT cust_name, cust_contact, prod_id

FROM customers, orders, orderitems

WHERE customers.cust_id = orders.cust_id AND orderitems.order_num = orders.order_num;

# “视图”的使用,只需要像查询普通表一样

SELECT cust_name, cust_contact

FROM productcustomers

WHERE prod_id = ‘TNT2′;

ShopNC的创业之路

2
挖一下

创业是艰难的,尤其是程序员创业。资金及管理经验的匮乏,直接影响了初期的生死存亡。在2006年5月,我从北京以一个程序员的身份回到了故乡天津。本来想找一个适合自己的职位,但是发现在当时的天津的互联网企业中,自己所学根本找不到一个可以施展自己能力的公司。我思考再三,决定选定一个方向来自己发展。

2006年7月,ShopNC的开发团队在一个不足40平米的办公间正式开始招募了!

万里之行始于足下,选择电子商务的方向是经过我深思熟虑的。第一,我要根据自己的技术经验来选择方向,我2004年开始,就给台湾某公司一直做电子商务软件的,尤其是网店软件的开发,积累了很多开发经验;第二,国内网店系统杂多,专业性高的却还是少;第三,电子商务是最接近金流、物流的部分,最容易与传统行业相结合。

因为前期都是开发周期,所以招聘来的人,不仅仅要培训技术,还要自己作为主力,进行程序的编写。通常是白天忙公司的事情,晚上自己忙写代码。同时为了生存,还要考虑接一些项目来养活人。这个阶段是最艰苦的。大概有1年多吧。一台电脑,一盒烟,累了睡在沙发,这期间我基本家也不回,吃住都在公司里。

在此期间,我深刻体会到了钱的重要性。没有资金的进入,是无法运作任何商业体的。有得时候真的需要为了钱而去暂时放下追求理想的步伐,为了下一次启程而继续资金。而做项目太多,影响产品的开发,已经是必然了。这个时候只有考虑如何尽量规律化项目的规模,收入的规模来尽量减少对产品开发的伤害。所以在成立公司不久,我就在寻求这样的客户。

在2007年3月份我们正式与天津创业环保股份(股票代码600874)建立了合作关系。并积极为其开发了公司内部系统及承接了其各个子公司的项目开发任务。事至今日,这样的合作已经快有2年之久了,并且还在继续并很规律的合作下去。类似的还有2008年2月,我们又开始与天津市公检法系统合作,并与2008年协助天津南开法院,河北法院开发了部分办公系统软件(基于.net框架)。并且这样的关系也是将长久下去。同样有这样的稳定的资金来源,我才能更多精力的投入产品的开发。

2007年,我选择了台湾市场作为单用户系统的第一市场。大陆的单用户市场很混乱,免费的,开源的满天飞,基本都是赔钱赚吆喝。在2007年中,我在台湾市场成功的拥有了一批商业客户,使得产品的成熟程度得到了进一步的完善。大陆市场方面,我们考虑在2009年初会把单用户在大陆市场正式开始推广。

2007年8月份,我做了一个重大的选择,就是暂时在大陆市场放弃单用户的开发,转向多用户商城系统的开发。我们严谨的策划了多用户的开发案,争取在系统架构,功能,扩展等方面能超出国内其他系统。历经1年之久,在2008年9月份,我们推出了ShopNC多用户商城系统1.93版本,并预期在12月初推出我们的2.2正式版本。

可能在很多人看来,以上的过程不过2年时间,弹指即过。可是在实际过程中,每一次公司策略的调整都是需要付出绞尽脑汁的考虑,以金钱或时间作为代价交学费,也是无法避免的。

2006年7月创业初始,我身负22.5万的家庭债务,手头没有任何积蓄的情况下,工作室建立了。(2007年7月份,我才正式注册了天津市网城创想科技有限责任公司。之前一直是工作室模式。),而启动资金是向我当时的女朋友手里借了7000元开始的。交完房租,买了4张桌椅,从家里搬个2台电脑这就是全部家当,唯有简陋可以形容了。

我是一个技术人员,一点生意的经验都没有,面对每个月的固定支出,每季度的房租都是陌生并恐惧的心里,但是不能向任何人讲,只有自己扛着,只有不断给自己信心,不断分析解决方法谋取生存的空间。那个时候根本谈不到什么长远的发展,生存才是硬道理。“站直了,别趴下”,这是我对自己第一年的最高要求。

在2007年春节期间,因为狭小的办公空间已经不能满足需求了,而且来了客户,也很难堪。我考虑换一个大的办公环境。如果租写字楼,1块钱一度的电费就是一个比较大的支出。我考虑再三,选择了商住两用的小区,作为办公环境。“开源节流“是我一直崇尚的。

2007年3月份,工作室正式迁入天津市富力城天越园。租下138平米的一个房子。这个在当时的我来说,也是一个很大的举动了。因为对于当时我的资金层面而言,这是一个很严峻的考验。

生存与发展在某些时候是一对矛盾体。相信玩过即时战略游戏的朋友都有感触。与电脑对打的时候,你可以有时间不停的完善自己以后,再去消灭敌人。而与人对打的时候,尤其是高手对垒,选择一个正确的突击方法,看上去不起眼的兵力,既可在最短时间消灭对手。而那些过于要求完善自己的玩家,基本都是战败者。我常常给我的朋友讲一个故事:有2个人,要穿越很大的一个沙漠。其中一个人赶上牛车,带上很多食物,一天10公里的速度在前进;另外一个只带了3天的干粮,轻装上路,一天100公里的速度在前进。哪么他们谁能活着穿越呢?我相信仁者见仁,智者见智。但是我个人,会选择后者。

2007年的一年,做了几件重要的事情,第一是正式成立了公司,因为要去承接大公司项目,这是必须的。第二件事情,为了稳定公司的收支,接了一些外包项目。因为太需要钱了!如果说一个人在商业发展的道路上有4种境界。第一种是自雇,例如soho一族,自给自足,自己剥削自己;第二种是众雇,就是你自己没有钱,却要养活一群你雇佣的人,属于被雇佣者剥削雇佣者;第三种是企业,属于雇佣者剥削被雇佣者;第四种就是投资者。毫无疑问,我当时正在第二阶段痛苦煎熬着。我想很多创业者也有这样的感受吧!

所幸,2007年的一年还是有收获的,我制定的承接项目规则被严格执行了。那些小的,很难形成长久关系的项目被剔除了。成功的保留了几个相对省心省力长久的项目还在继续着。也很大程度上缓解我一部分资金压力。

走入2008年,公司已经初具规模,各方面条件都相对初期成熟了很多。春节期间,我制定了2008年~2009年为技术开发年的公司方针。只要我有3个月的工资储备,我就往前走,绝对不能胡乱接项目了。这一年,我也完成了人生大事,我结婚了。找一个好女人,省心是最重要的。同时做公司与做工作室最大的不同,就是要面对复杂的财务及相关管理部门。

另外一个重点,就是技术方面的问题。技术的先进性是产品先进性的最大保证。而将开发团队管理好,更是产品制造业中最重要的环节。团队必须是一个平衡的梯队,团队中的Leader,他将负责起整体产品架构方向性的重任,并要有足够的能力去解决核心技术问题。还要有一些能力强,踏实,责任心重,荣誉感强的程序员,可以为共同的事业及目标通宵达旦。而负责项目定制的团队,必须要找可靠的人去做。

对于开发工具及管理工具的使用,公司代码的主体架构,要让整个团队的人都要纯熟的使用。不能说某一个人的离开而影响开发的进展,起码要将这样的隐患降低到最小伤害。

关于技术方面如果细说起来,还有太多太多需要去说的。2年来我总结了简单的几点。对工作岗位是:“定岗不定人”;对技术水平的要求是:“与时俱进”;对技术人员是:“严格要求”;对项目管理是:“每日跟进”;对客户的选择是:“则善而侍,遇恶则避”。

走到今天,我公司的多用户商城系统已经基本完善了,并且取得了一定的市场份额。但是我们依然还有很大的发展空间,还有很多值得去做,需要去做的工作,而这也是我未来很多年中都要专心致力去做的事情。

在此,我要呼吁想要创业的所有草根们!我们可以被人忽视,但是我们一定要给自己信心。敏于行而慎于言,讷于言而敏于行。坚定信心,把执行力与缜密的头脑变成我们最强有力的武器,为我们的事业打拼出一块自己的天地。我们一起努力。

从Windows 1.0到Vista启动画面回顾

0
挖一下

成千上万的PC用户每天打开电脑首先看到的就是Windows启动画面,从1985年到2008年,跨跃24年的时间里,计算机用户们到底经历了什么样的视觉历程?

总有人说,微软的这个系统不好,那个系统不好。其实大家的说法也对,也不对。毕竟没有任何技术都能够一步到位(不然我们现在直接做着飞碟去外层空间交友了),从略长的时间角度来讲,Windows很明显地在进步。

虽然有很多人张口骂Windows ME的失败,但是ME比起Windows98如何?ME里面内置了很多功能都是XP直接采用的。而且,很多骂ME的人都是道听途说,总感觉那么多人骂肯定有被骂的道理,于是跟着骂,其实自己压根没见过ME是啥样。

我们带大家再来回顾从Windows 1.0到Windows vista的启动画面发展进程:

winws
1985.11.20Windows1.01 —— 最早的“蓝屏”
winws
1987.11.1 Windows 2.03 ——微软标识成形
winws
1990.5.22 Windows 3.0

winws
1992.3.18 Windows 3.1 —— 首次出现窗口旗帜

winws
1993.11.1 Windows for Workgroups 3.11
winws
1993.7.27 Windows NT 3.1
winws
1993.7.27 Windows NT 3.1 AdvancedServer
winws
1994.9.21 Windows NT Workstation 3.5
winws
1995.5.30 Windows NT Workstation 3.51
winws
1995.5.30 Windows NT Server 3.51
winws
1995.8.24 Windows 95 ——“蓝天白云”并突出显示了集成的IE浏览器
winws
1996.8.24 Windows NT Workstation 4.0
winws
1996.8.24 Windows NT Server 4.0
winws
1998.6.25 Windows 98
winws
2000.2.17 Windows 2000 Professional —— 第一次使用进度条
winws
2000.9.14 Windows Millennium Edition
winws
2001.10.25 Windows XP Home Edition —— 进度条改成了循环滚动样式
winws
2001.10.25 Windows XP Professional Edition
winws
2003.3.28 Windows XP 64-Bit Edition
winws
2003.4.24 Windows Server 2003
winws
2004.8.6 Windows XP SP2 —— Professional字样被去掉
winws
2007.1.30Windows Vista—— 改用黑屏

winws
2007.1.30 Windows Vista —— 第二部分,看来微软不过瘾,非要在Vista里加上两个启动画面。

发现一个不错的EXCEL操作类

1
挖一下

点我下载

刚刚用这类读取XLS发现速度很快很好,拿出来跟大家分享。

←Older