编程开发 类目

学会编程我们能够和计算机沟通

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。

继续阅读

MySQL Python 教程(二)

原文链接:http://zetcode.com/databases/mysqlpythontutorial/
翻译作者:kodango dangoakachan at foxmail dot com
译文链接:
a. https://kodango.com/mysql-python-tutorial-part-one
b. https://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. https://kodango.com/mysql-python-tutorial-part-one
b. https://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操作系统之上。

继续阅读

理解 Python 语言中的 defaultdict

原作者: Jason Kirtland
日期: January 13th, 2009
许可证: Creative Commons Attribution-Share Alike 3.0
原文链接(PPT): http://discorporate.us/jek/talks/defaultdict/
翻译作者:kodango <dangoakachan@foxmail.com>
翻译时间:March 17th, 2012

今天看到一篇讲defaultdict的PPT,同时第一次见到__missing__()这个方法,好奇之下,仔细阅读了这篇PPT。看完之后随手做笔记,分享给有需要的人。准确地说,这篇文章不是纯粹的翻译,因为原文本身只是一份PPT。文章的大多数文字内容,都是本人的阅读心得。

默认值可以很方便

众所周知,在Python中如果访问字典中不存在的键,会引发KeyError异常(JavaScript中如果对象中不存在某个属性,则返回undefined)。但是有时候,字典中的每个键都存在默认值是非常方便的。例如下面的例子:

strings = ('puppy', 'kitten', 'puppy', 'puppy',
           'weasel', 'puppy', 'kitten', 'puppy')
counts = {}

for kw in strings:
    counts[kw] += 1

该例子统计strings中某个单词出现的次数,并在counts字典中作记录。单词每出现一次,在counts相对应的键所存的值数字加1。但是事实上,运行这段代码会抛出KeyError异常,出现的时机是每个单词第一次统计的时候,因为Python的dict中不存在默认值的说法,可以在Python命令行中验证:

>>> counts = dict()
>>> counts
{}
>>> counts['puppy'] += 1
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
KeyError: 'puppy'

继续阅读

理解 Python 中的 *args 和 **kwargs

Python是支持可变参数的,最简单的方法莫过于使用默认参数,例如:

def test_defargs(one, two = 2):
   print 'Required argument: ', one
   print 'Optional argument: ', two

test_defargs(1)
# result:
# Required argument: 1
# Optional argument: 2

test_defargs(1, 3)
# result:
# Required argument: 1
# Optional argument: 3

当然,本文章的主题并不是讲默认参数,而是另外一种达到可变参数 (Variable Argument) 的方法:使用*args和**kwargs语法。其中,*args是可变的positional arguments列表,**kwargs是可变的keyword arguments列表。并且,*args必须位于**kwargs之前,因为positional arguments必须位于keyword arguments之前。

继续阅读

PySqlite 学习笔记

这是一篇老笔记,原来是放在旧博客上的,最近因为公司内部一个小东西,想使用简单点的数据库来存储数据,就想起用SQLite来做,上网搜索一些教程。竟然发现,原来一年多前,我也学过一阵子,可惜因为不常用,现在已经基本忘记光光了,加上自己对数据库向来不是非常熟悉,就特地放到新博客上,顺便回顾一下。

这篇笔记的主要内容来源于python之sqlite3使用详解PySqlite简明教程

SQlite这个小型数据库,经常在Firefox或者其它软件中看到,它貌似没有独立的维护进程,而是把所有数据都存放在一个单独的文件中。上网搜了下资料,看了看Python上的pysqlite模块,它正是Python中对sqlite的封装实现。

数据库操作

Python的数据库模块都有统一的接口标准,所以数据库操作都基本上是统一的,基本上分成以下几步(假设数据库模块为db):

  1. 用db.connect()创建数据库连接,连接对象为conn。
  2. 如果不需要返回查询结果,就直接调用conn.execute()。
  3. 如果需要返回查询结果,则需要首先通过conn.cursor()创建游标对象cur,并使用cur.fetchone()等函数获取查询结果。
  4. 根据数据库隔离级别的不同,修改数据库后,可能需要使用conn.commit()手动提交事务。
  5. 调用相应的close()方法关闭cur及conn。

继续阅读

博客添加回到顶部按钮

博客的文章往往篇幅比较长,如果访客要访问博客的其它文章(例如通过侧栏的Widgets访问相关的文章)就需要滚动鼠标,移动到页面的头部。比较人性的一个设计是,在页面的底部(或者中靠近下的位置)添加一个“回到页面顶部”的按钮,可以快速定位到文章的顶部位置。

这个功能设计起来不难,可以采用如一文中提到的锚链接形式,例如回到顶部按钮是一个链接:

<a href="#top">Top</a>

将其放到页面底部,点击该链接可以直接定位到页面顶部。但是如果我们不希望用链接来实现呢,而是模拟一个按钮(用span),并且希望按下回到顶部按钮的时候,可以比较平滑地回到顶部,那该怎么做呢?代码非常简单,这里只用到些许的CSS样式以及jQuery代码。

首先在在文章页面body底部添加以下代码(index.php或者single.php):

<span id="back-to-top">Top</span>

为了方便起见,以上按钮的代码在jQuery中创建添加,不需要手动去修改php文件。同时,利用jQuery完成按钮的行为,主要通过监听window的onscroll事件,当滚动距页面顶部超过100px的时候,淡入显示按钮。当滚动距页面顶部少于100px的时候,淡出隐藏按钮。使用jQuery的animate函数,可以实现平滑地滚动效果(利用document.body或者document.documentElement的scrollTop属性完成动画效果)。

添加的jQuery代码如下所示:

/* Add a back to top button */
function back_to_top()
{
    /* Cache back-to-top button object */
    var $top = $('<span id="back-to-top">Top</span>').appendTo('body');

    /* Cross-browser compatible in scrollTop */
    var $body = (!window.opera) ? $('html, body') : (document.compatMode == 'CSS1Compat'
        ? $('html') : $('body'));

    if ($top.length == 0)
         return;
 
    /* Hide back-to-top button at first */
    $top.hide();
 
    /* Fade in back-to-top button when need */
    $(window).scroll(function () {
        if ($(this).scrollTop() > 100) {
            $top.fadeIn();
        } else {
            $top.fadeOut();
        }
    });
 
    /* Scroll to top when click back-to-top button */
    $top.click(function () {
        $body.animate({ scrollTop: 0 }, 800);
    });
}

back_to_top();

同时在博客样式(style.css)中添加以下自定义的样式内容:

#back-to-top {
    background-color: #F5F5F5;
    bottom: 0;
    box-shadow: 0 0 6px #808080;
    color: #444444;
    padding: 5px 10px;
    position: fixed;
    right: 50px;
    cursor: pointer;
}

这里将按钮固定定位到(position: fixed)页面右下角,并且添加边框阴影等效果。

最后附上一段区分外部链接的代码片断(摘自Learning jQuery 3rd edition)

    /* Add tag next to the external link */
    $('.column .post-entry a').not(':has(img)').filter(function() {
        return this.hostname && this.hostname != location.hostname;
    }).addClass('external').attr('target', '_blank');