Flask支持多语言站点


Flask的多语言国际化可以使用Flask-Babel插件,在此不再细述,但对于所谓的多语言站点(即形如example.com/zh/uri、example.com/en/uri或者zh.example.com、en.example.com)文档上却未作细述

有一个 Flask URL Processors 需要对所有的uri都额外增加一个lang_code的前缀,路由数较少时没什么问题,但路由数较多时太过麻烦

实现example.com/en/uri可以有多种方式,除了使用Flask URL Processors中介绍的外,还可以

使用nginx重定向uri

这应该是各种方式里最简单的一种

location ~ ^/en/ {
    rewrite ^/en/(.*)$ /$1 last;
}
location = /en {
    rewrite ^/(.*)$ /index …

ansible笔记


ansible动态解析inventory

ansible调用inventory模块时总会调用一个文件或脚本来进行处理, 但我想要动态的解析inventory, 即直接传入一个字符串而不是文件, 直接调用ansible的接口来进行解析(不同格式的inventory也可以手动解析,比如yaml格式可以使用pyyaml解析,不过直接使用ansible接口会更方便一些)

但问题是ansible没有直接可供调用的接口, 不过可以直接查看ansible源码,找到相应的解析函数,封装一下即可

查找源码, 根据 InventoryManager 传递的source变量找到parse_sources这个函数

class InventoryManager(object):
    def parse_sources(self, cache=False):
        ''' iterate over inventory sources and parse each one to populate it'''

        self._setup_inventory_plugins()
        ...

然后再根据

def _setup_inventory_plugins(self):
    ''' sets up loaded inventory plugins for usage '''

    inventory_loader = PluginLoader('InventoryModule', 'ansible …

为pelican添加子站点功能


Table of Contents

创建翻译

babel-init:
    cd $(THEMEDIR) && pybabel extract -F babel.cfg -k lazy_gettext -o messages.pot ./ && pybabel init -i messages.pot -d translations -l en

babel-update:
    cd $(THEMEDIR) && pybabel extract -F babel.cfg -k lazy_gettext -o messages.pot ./ && pybabel update -i messages.pot -d translations

babel-compile:
    cd $(THEMEDIR) && pybabel compile -d translations

动态变量

在模板里,我有一些动态变量需要翻译,比如在分类里的 Python 需要翻译成 生活苦短,但很不幸, Babel …

为pelican添加文章加密功能


pelican是一个静态博客系统,很早之前就想要实现一个加密pelican文章的功能,但一直没什么时间,这次总算静下心花两天时间搞定了

为什么不用现有的插件encript-content

因为自己实现更有成就感啊!!!

前言

因为我不仅有静态博客honmaple.me,还有一个动态博客honmaple.com,所以此次加密功能我会在动态博客那边添加一个验证密码的接口,来对密码进行验证以及对加密文章进行解密,虽然验证也可以使用crypto-js.js进行双向解密,但还是觉得自定义的接口更安全一些。

自定义pelican插件

加密算法

加密算法我使用cryptography,使用起来很简单

>>> from cryptography.fernet import Fernet
>>> # Put this somewhere safe!
>>> key = Fernet.generate_key()
>>> f = Fernet(key)
>>> token = f.encrypt(b"A really secret message. Not for …

flask_maple文档


安装

To install Flask-Maple:

pip install flask-maple

Or alternatively, you can download the repository and install manually by doing:

git clone git …

python尾递归优化


参考 这里

class TailRecurseException(BaseException):
    def __init__(self, args, kwargs):
        self.args = args
        self.kwargs = kwargs


def tail_call_optimized(g):
    """
    This function decorates a function with tail call
    optimization. It does this by throwing an exception
    if it is it's own grandparent, and catching such
    exceptions to fake the tail call optimization.

    This function fails if the decorated
    function recurses in a non-tail context.
    """

    def …

使用tornado实时输出日志


import tornado
from tornado.web import Application
from tornado.web import RequestHandler
from tornado.websocket import WebSocketHandler
import os
import json

template = '''<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8"/>
    <title>Document</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <script src="https://cdn.bootcss.com/jquery/2.1.4/jquery.min.js"></script>
    <script src="https://cdn.bootcss.com/bootstrap/3 …

为pelican增加上一篇下一篇功能


功能实现很简单, pelican也有类似的插件实现 https://github.com/getpelican/pelican-plugins/tree/master/neighbors

不过自己实现起来更爽不是吗? 而且类似prev_article_in_categoryprev_article_in_subcategory的功能我并不需要

首先参考pelican的文档,基础实现

def add_neighbors(generator):
    ....

def register():
    signals.article_generator_finalized.connect(add_neighbors)

然后在generator.articles列表上进行操作,为article增加previous_articlenext_article对象

先进行排序(按时间)

articles = generator.articles
articles.sort(key=(lambda x: x.date), reverse=True)

然后可以使用iter关键字,把列表变成生成器,使用next()( python2用a.next(),python3用a.__next__())获取下一个可迭代对象

pre_article …

tornado中session实现


tornado中默认没有session的实现,虽然默认的 set_secure_cookie 已经足够安全了,但更安全的应该是客户端保存session_id,服务端保存对应的信息

注:保存在redis中的经测试是可以的,保存在内存中的貌似还不行

给出源码:

from uuid import uuid4
from redis import StrictRedis
from functools import wraps
from datetime import datetime, timedelta
from pytz import timezone


def singleton(cls):
    instances = {}

    @wraps(cls)
    def getinstance(*args, **kw):
        if cls not in instances:
            instances[cls] = cls(*args, **kw)
        return instances[cls]

    return getinstance


def current_time(tz=None):
    if tz is None …

一个简单的数据分组算法


Table of Contents

之前有这么一个需求

将数据按照时间分组,比如说每5分钟为一组,或者每30分钟为一组,开始时间如果分钟数大于等于30分钟,则设置为30,如果小于30,则设置为0(也可以设置为更复杂的逻辑)

当然中间还有一些数据的统计,分析和计算暂时不管

获取开始时间

def get_start_date(start_date):
    time = datetime.fromtimestamp(int(start_date) / 1000)
    if time.minute >= 30:
        minute = 30
    else:
        minute = 0
    start_date = datetime(time.year, time.month, time.day, time.hour, minute,
                          0)
    start_date = mktime(start_date.timetuple()) * 1000
    return start_date

开始时间很简单,需要注意的是设置分钟,需要将时间戳转换为datetime,设置分钟数后再将datetime转为时间戳

time = datetime.fromtimestamp(int(start_date) / 1000 …