主要记录最近遇到的一些开发问题,解决方法。
1. Python 中的序列化与反序列化
序列化,将内存对象转化为可存储或传输序列的过程。反序列化,把序列化序列重新转化为内存对象的过程。Json 和 Pickle 是 Python 中常用的两个序列化处理模块。
Json VS Pickle:
- Json 实现的是内存对象与 Json 字符串的转换,Pickle 实现的是内存对象与字节对象的转换
- Json 格式广泛应用于除 Python 外的其他领域,Pickle 是 Python 独有的
- Json 只能序列化 Python 内置的基本数据类型对象,Pickle 可以序列化一切对象,包括函数
- cPickle 是 Pickle 的 C 语言实现,常用来替换 Pickle 以提升性能
使用示例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| # -*- coding: utf-8 -*-
import json
import pickle
obj = {'a': 'b', 'c': 'd'}
ps = pickle.dumps(obj)
print ps
# "(dp0\nS'a'\np1\nS'b'\np2\nsS'c'\np3\nS'd'\np4\ns."
js = json.dumps(obj)
print js
# {"a": "b", "c": "d"}
print pickle.loads(ps)
# {'a': 'b', 'c': 'd'}
print json.loads(js)
# {u'a': u'b', u'c': u'd'}
|
除此之外,对字符串还可以进行压缩,以节省存储:
1
2
3
4
5
6
7
8
| import cPickle as pickle
import zlib
# 序列化,并压缩
compressed = zlib.compress(pickle.dumps(obj))
# 解压缩,反序列化
obj = pickle.loads(zlib.decompress(compressed))
|
2. Django CSRF
django.middleware.csrf.CsrfViewMiddleware
处理逻辑:
进入 views 函数处理之前,如果 cookies 里面有 csrf token,则将其设置在 request.Meta 中,否则生成一个 token。如果不是 GET、HEAD 等方法则,校验 CSRF。
校验规则:从 Cookie 中取出 csrf token 与 POST 请求中的 csrfmiddlewaretoken 或者 HTTP_X_CSRFTOKEN 进行比较。如果两者相等,则通过校验,否则返回 403。
在返回响应之前,如果设置过 CSRF_COOKIE_USED,则会将 csrf token 设置到 Cookie 中。通常有两种方式设置 CSRF_COOKIE_USED:
- 直接使用
django.middleware.csrf.get_token
函数获取 csrf token - 配置
django.template.context_processors.csrf
上下文处理器,在模板里面渲染 csrf token,实际上还是调用了 get_token 函数
下面是摘取的部分 Django 源码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
| class CsrfViewMiddleware(object):
def process_view(self, request, callback, callback_args, callback_kwargs):
try:
csrf_token = _sanitize_token(
request.COOKIES[settings.CSRF_COOKIE_NAME])
request.META['CSRF_COOKIE'] = csrf_token
except KeyError:
request.META["CSRF_COOKIE"] = _get_new_csrf_key()
if request.method == "POST":
request_csrf_token = request.POST.get('csrfmiddlewaretoken', '')
if request_csrf_token == "":
request_csrf_token = request.META.get('HTTP_X_CSRFTOKEN', '')
if not constant_time_compare(request_csrf_token, csrf_token):
return self._reject(request, REASON_BAD_TOKEN)
def process_response(self, request, response):
if request.META.get("CSRF_COOKIE") is None:
return response
if not request.META.get("CSRF_COOKIE_USED", False):
return response
response.set_cookie(settings.CSRF_COOKIE_NAME,
request.META["CSRF_COOKIE"],
max_age=settings.CSRF_COOKIE_AGE,
domain=settings.CSRF_COOKIE_DOMAIN,
path=settings.CSRF_COOKIE_PATH,
secure=settings.CSRF_COOKIE_SECURE,
httponly=settings.CSRF_COOKIE_HTTPONLY
)
return response
|
参数解释:
- max_age: cookie的生命长度,默认为None,浏览器关闭 cookie 立即失效
- expires: cookie 过期时间时间点,默认为None,浏览器关闭 cookie 立即失效
- path: Cookie 生效的路径,/ 表示根路径,根路径的cookie可以被任何url的页面访问
- domain: 默认值为 None,设置该 Cookie 的网页所在的域名None
- secure: 用来设置 Cookie 只在确保安全的请求中才会发送。当请求是 HTTPS 或者其他安全协议时,包含 secure 选项的 Cookie 才能被保存到浏览器或者发送至服务器。
- httponly: 只能 http 协议传输,无法被 JavaScript 获取(不是绝对,底层抓包可以获取到也可以被覆盖)默认值 False。
Django 中关于 CSRF 的默认配置:
1
2
3
4
5
6
7
| # Settings for CSRF cookie.
CSRF_COOKIE_NAME = 'csrftoken'
CSRF_COOKIE_AGE = 60 * 60 * 24 * 7 * 52
CSRF_COOKIE_DOMAIN = None
CSRF_COOKIE_PATH = '/'
CSRF_COOKIE_SECURE = False
CSRF_COOKIE_HTTPONLY = False
|
3. djcelery_crontabschedule already exists 错误
使用版本:
- Django==1.8.3
- celery==3.1.18
- django-celery==3.1.16
升级 django-celery==3.2.2 时,执行 python manage.py migrate
,报错:
1
2
3
| File "/app/.heroku/python/lib/python2.7/site-packages/pymysql/err.py", line 115, in _check_mysql_exception
raise InternalError(errno, errorvalue)
django.db.utils.InternalError: (1050, u"Table 'djcelery_crontabschedule' already exists")
|
在 django-celery 的 GitHub 更新日志中提到:
在 3.1.17 更新版本之后,新增了 Django migrations。
如果已经存在 djcelery_*
等表,则会导致执行 $python manage.py migrate
时报错。升级依赖的版本库时,需要注意版本的兼容性。
4. 如何合并两个 fork 仓库
查看本地远程源:
1
2
3
| git remote -v
origin https://github.com/yourname/celery.git (fetch)
origin https://github.com/yourname/celery.git (push)
|
添加需要合并的远程源:
1
| git remote add upstream https://github.com/celery/celery.git
|
查看本地远程源:
1
2
3
4
5
| git remote -v
origin https://github.com/yourname/celery.git (fetch)
origin https://github.com/yourname/celery.git (push)
upstream https://github.com/celery/celery.git (fetch)
upstream https://github.com/celery/celery.git (push)
|
获取远程源的最新更新:
1
2
3
4
| git fetch upstream
From https://github.com/celery/celery
* [new branch] var.ci -> upstream/var.ci
* [new branch] workhorse-pool -> upstream/workhorse-pool
|
合并远程 fork 分支到当前分支:
1
| git merge upstream/master
|
5. 监控 Celery 的工具 - Flower
Flower 是基于 Web 的 Celery 监控和管理工具。提供的功能有:
- 查看 worker 状态和统计信息
- 关闭和重启 worker 实例
- 控制 worker 池的大小
- 显示 task 详细信息
- 查看当前运行的 task
- 查看 tasks 的调度
- 唤醒和终止tasks
- …
安装:
运行:
1
| python manage.py celery flower
|
打开:http://localhost:5555,访问: