Python 日志模块使用

Python内置了很多非常使用的模块,logging 模块是用于控制和输出日志的,它是一个非常强大的日志模块,可以按照不同的需求配置。它的官方文档地址是在这里

我自己也用过几次logging模块,但是前面用的时候都把它用得太复杂了,还自己封装了下。其实,有些代码越是简单越好,写得复杂得反而不容易扩展和使用。

以下是我在脚本中用到的一段代码:

def init_log(log_file):
    '''Initialize logging module.
    '''
    logger = logging.getLogger()
    logger.setLevel(logging.DEBUG)

    formatter = logging.Formatter('[%(levelname)s] %(message)s')

    # Create a file handler to store error messages
    fhdr = logging.FileHandler(log_file, mode = 'w')
    fhdr.setLevel(logging.ERROR)
    fhdr.setFormatter(formatter)

    # Create a stream handler to print all messages to console 
    chdr = logging.StreamHandler()
    chdr.setFormatter(formatter)

    logger.addHandler(fhdr)
    logger.addHandler(chdr)

    return logger

代码的意思很简单,这里就不多加解释了,需要注意的是第5行不能少,要不然会出现问题。因为当logging模块输出的日志分成多个级别,例如DEBUG、INFO、WARN、ERROR等。当没有通过setLevel方法设置日志级别的话,系统默认的日志级别是WARN,也就是说只胡日志级别大于等于WARN的日志才会输出可见,例如ERROR,而日志级别比它低的则被过滤掉了,例如DEBUG。

那为什么这一行不能少呢?因为当一条日志要打印输出时,首先会看这条日志的级别是否大于logging.setLevel设置的级别或者默认的WARN,如果不是则直接过滤掉;如果大于,则会发送给Logger对象绑定的各个handler对象,交由它们进一步处理日志,或者输出到屏幕,或者写入到文件中。而每个handler对象也会有它自己设置的日志级别,然后再进一步地过滤。所以如果不包含第5行,然后StreamHandler对象设置的日志级别是DEBUG的话,其实是没有意义的。

使用方法:

logger = init_logger('test.log')
logger.debug('%s, %s', 'hello', 'world');
logger.info(...)
logger.warn(...)
logger.error(...)

一个奇怪的 echo 结果

昨天经阮哥指点后,写一个检查redis-server的内存消耗的脚本。脚本本身不复杂,因为redis-cli已经提供了查询接口。

# redis-cli -p yourt_port info | grep 'used_memory'

# resuts:
# used_memory:122088016
# used_memory_human:116.43M
# used_memory_rss:128057344
# used_memory_peak:122079336
# used_memory_peak_human:116.42M

一般会选择提取出used_memory_human的结果,但是考虑到万一内存消耗上G了呢?那么这里也要进行一个单位转换,干脆就提取used_memory这个值,以字节为单位的,然后在这个值基础上除以1024*1024换算成MB。

查看全文

Sed 命令地址匹配问题总结

这个问题来源于ChinaUnix的一篇帖子“sed地址和模式匹配的问题”。

man sed手册说明

Sed默认的命令执行范围是全局的,如果想仅对其中部分行执行命令,可以使用地址限制。在Manual手册中有一节关于地址的描述,摘取部分如下:

Sed commands can be given with no addresses, in which case the command will be executed for all input lines;

Sed默认是全局编辑的,因此如果不明确指定行的话,命令会在所有输入行上执行。

with one address, in which case the command will only be executed for input lines which match that address;

如果指定一个行地址,那么sed命令就限制在那一行执行。

or with two addresses, in which case the command will be executed for all input lines which match the inclusive range of lines starting from the first address and continuing to the second address.

如果给了两个地址,即地址对(或者地址范围),则命令在匹配的这个地址范围内执行。但是需要注意的几点是:

The syntax is addr1,addr2 (i.e., the addresses are separated by a comma); the line which addr1 matched will always be accepted, even if addr2 selects an earlier line; If addr2 is a regexp, it will not be tested against the line that addr1 matched.

查看全文

什么是交互式登录 Shell

今天在看~/.bashrc文件的时候看到一行,对它的意思不是非常了解:

[[ $- != *i* ]] && return

就特意上Google搜索了一下,对于搜索关键字是符号(这里是$-)的,我是不怎么抱希望的。所以干脆将$-的结果(himBh)放到Google一起搜索。果然找到两篇不错的帖子:

这两个帖子都是在ChinaUnix论坛上的。这些老论坛虽然人气不行,但是一些资源还是很赞的,这些总结帖都非常好。尤其是第一篇非常值得一读,我只是看了其中一部分。对sh和bash的区别并没有仔细看,觉得这些没必要去死记,到时候碰到问题再去理解就好,要不然就太枯燥了。

Linux用了这么多年,Shell一直在用,执行命令,安装软件,配置文件,以及编写脚本,但是说真地,我对Shell一直不是非常了解,几乎没看过和它相关的任务手册和文档。一般系统中最常见的Shell还是Bash。Bash的手册非常长,我是坚决不看的,头痛。后果就是对Bash的一些现象一知半解,其实这些基本上在手册上都是有写的。

查看全文

使用命令行启动 VirtualBox 虚拟机

装上 VirtualBox 就琢磨着如何让它开机自动启动,又或者能够通过命令行的形式直接启动指定的虚拟机。看了下VirtualBox的官方文档,发现有一个命令可以满足我的需求,即VBoxManage。VBoxManage提供了一系列的虚拟机管理命令,包括创建/删除/启动/修改等等,这里不一一列举。有点像Xen的XM命令。不过这里只关心启动虚拟机的命令:VBoxManage startvm。VBoxManage的完整命令列表可以参考这里

VBoxManage startvm子命令可以开启一台状态为关闭或者保存的虚拟机。该命令的语法为:

VBoxManage startvm  uuid>|name... [--type gui|sdl|headless]

可以通过虚拟机的uuid或者name来指定某台虚拟机,可以通过另外一个子命令list列出系统已有的虚拟机:

$ VBoxManage list vms
"XP" {8842d793-228c-458e-a880-8051193fd2db}

我系统上已经安装了一台名为XP的虚拟机,后面括号内部的是它的UUID。

查看全文

MySQL Python 教程(二)

原文链接:http://zetcode.com/databases/mysqlpythontutorial/
翻译作者:kodango dangoakachan at foxmail dot com
译文链接:
a. http://kodango.com/mysql-python-tutorial-part-one
b. http://kodango.com/mysql-python-tutorial-part-two

译者注:本文的前半部分请看上一篇文章

字典游标

在 MySQLdb 模块中有许多种游标类型。默认的游标类型以元组的元组形式返回数据。当我们使用字典游标时,这些数据是以Python字典的形式返回。这样一来,我们就可以通过列名来访问数据。

#!/usr/bin/python
# -*- coding: utf-8 -*-

import MySQLdb as mdb
import sys

con = mdb.connect('localhost', 'testuser', 
    'test623', 'testdb')

with con:

    cur = con.cursor(mdb.cursors.DictCursor)
    cur.execute("SELECT * FROM Writers")

    rows = cur.fetchall()

    for row in rows:
        print "%s %s" % (row["Id"], row["Name"])

查看全文

MySQL Python 教程(一)

原文链接:http://zetcode.com/databases/mysqlpythontutorial/
翻译作者:kodango dangoakachan at foxmail dot com
译文链接:
a. http://kodango.com/mysql-python-tutorial-part-one
b. http://kodango.com/mysql-python-tutorial-part-two

关于本教程

这是一份介绍用Python语言操作MySQL数据库的教程,覆盖了基础的Python MySQL编程内容。本教程中使用了MySQLdb模块,文中的例子在Ubuntu系统下运行和测试。

译者注:我使用ArchLinux,会在文中添加与ArchLinux相关的内容,例子也会一一在ArchLinux下验证。

在本站中,有许多与本文类似的教程,其中包括PostgreSQL PythonMySQL Visual BasicMySQL PHP。如果你需要更新与Python语言相关的知识,在这里还有一份完整的Python教程。你也可以考虑阅读MySQL教程

关于MySQL数据库

MySQL是一个领先的开源数据库管理系统。它是一个多用户,多线程的数据库管理系统。MySQL在网上非常流行,它与Linux、Apache、PHP一起组成LAMP平台,这是一个非常流行的Web平台。目前,MySQL是由甲骨文拥有。MySQL数据库可用于最重要的几个操作系统上。它能够运行在BSD UNIX,Linux,Windows或Mac操作系统之上。

查看全文

MySQL 笔记

这篇笔记,主要是为了记录 MySQL 一些有用的SQL语句和命令。以前在学校里,接触数据库不多,以至于在面试的时候总是被问得非常难堪。现在在公司里,突然发现好多东西是需要学的。

1. 列出所有的表

show tables;

2. 查询表结构

describe table_name;
show columns from table_name;
show create table table_name;

3. 查询表中的第几行

select * from table_name limit n;   查询前n行
select * from table_name limit n-1, m-n; 查询从第n行开始的m行的记录

4. 设置数据库编码

set names utf8;

查看全文