书写一月

从2017.3.7 开始在简书上第一篇,到今天,差不多1个月,24篇文章,覆盖随笔、摄影和编程,字数:6885,收获喜欢 11,粉丝 7。

公众号目前是104位订阅者。

blog 这里没有办法统计具体的人数,但从每篇 blog 的访问来看,是最多的,不过我估计绝大多数是各类 bot。

书写一月,感觉简书平台还是挺有趣的,体验也是做得最好,比用了十几年的 wp 还好。

互联网时代了,手机时代了,必须要改变一些思维方式了。

未来总是挑战重重。

又是清明

清明天气很好,难得出去逛街的我,到了港汇一游。

以前好像还是经常去港汇的,包括百脑汇和太平洋,后者现在已经几乎没有了,港汇还是很热闹。在肇嘉浜路上班的时候,特别是后期,经常中午走几个街口到港汇吃饭小聚。

景物都在,物是人非。烦恼果然是时时刻刻都有,放得下就是一天,放不下也是一天。

python 中使用装饰器来统一检查 flask 用户权限

最近在一个项目中,需要判断 restful 接口函数传入的时候,是否之前已经登录状态是某个特定用户,以及该用户有没有指定的权限。检查下来如果没有的话,立刻返回错误,中断功能。

遮掩的场景虽然也可以通过标准的调用函数来操作,但都不如用装饰器来得简单。都知道装饰器好用不好写,废话不说,先来看看这个场景怎么实现,还是有一定的通用性的。

def validate_current_is_admin(f):
    @functools.wraps(f)
    def decorated_function(*args, **kws):
        # 需要在登录状态调用, 检查是否为有admin权限的用户登录,
        # 如果不是,返回错误码;
        if g.user.user_name != 'admin':
            raise CustomFlaskErr(USER_MUST_HAS_ADMIN_PRIVILEGE, status_code=401)

        # 验证权限是否为 admin, 不是的话,返回401错误
        if g.user.role_id != Permission.ADMIN:
            raise CustomFlaskErr(USER_MUST_HAS_ADMIN_PRIVILEGE, status_code=401)

        return f(*args, **kws)

    return decorated_function

 

这是一个标准的装饰器的写法,如果你要写一个简单的装饰器,整个框架可以参考。

装饰器调用举例:

@app.route('/api/create_user', methods=['POST'])
@auth.login_required
@validate_current_is_admin
def create_user():

    # 获得参数
    user_name = request.json.get('user_name')
    password = request.json.get('password')
......

 

核心代码的业务逻辑也不复杂,根据 flask 的 g 对象中预存的用户 user 进行检查处理,flask 的这些定义非常灵活,flask.g 怎么使用可以查看 flask 的文档。

这里的user以及相关的属性属于具体业务逻辑,就不展开解释了,可以望文生义。

如果检查下来不符合的话,会调用自定义的 flask 错误,这部分内容可以查看之前写的 python flask 写 api 如何返回自定义错误

因为不对args和kws这些参数进行解析和处理,所处理的是 flask 全局对象。最后将参数都原路打包返回即可,没有问题的话交给使用装饰器的代码继续处理。

这个例子比较简单,主要还是熟悉装饰器的基本用法。

(首发简书

python flask 写 api 如何返回自定义错误

在 python 开发中,利用 flask 写 restful api 函数的时候,除了标准的400、500等这些返回码通过 abort() 返回以外,怎么另外返回自定义的错误代码和信息呢?

我们碰到的业务场景是对于api 输入参数的各类校验以及在业务逻辑执行的时候,都会返回统一的400代码,同时也会返回我们约定的描述详细错误的代码以及描述字符串,提供给调用方来处理,这样可以让其用户体验做得更好,同时详细错误代码和描述字符串也会自动打印在 log 日志中。

flask 的官方文档中告诉我们:

默认情况下,错误代码会显示一个黑白的错误页面。如果你要定制错误页面, 可以使用 errorhandler() 装饰器

在写 restful api 的时候,并没有页面可以返回,我们可以在 flask 提供的代码基础上稍加改造如下。

在你的初始化 flask app 的相关代码中加入下面两个函数:

@app.errorhandler(CustomFlaskErr)
def handle_flask_error(error):

    # response 的 json 内容为自定义错误代码和错误信息
    response = jsonify(error.to_dict())

    # response 返回 error 发生时定义的标准错误代码
    response.status_code = error.status_code

    return response

 

class CustomFlaskErr(Exception):

    # 默认的返回码
    status_code = 400

    # 自己定义了一个 return_code,作为更细颗粒度的错误代码
    def __init__(self, return_code=None, status_code=None, payload=None):
        Exception.__init__(self)
        self.return_code = return_code
        if status_code is not None:
            self.status_code = status_code
        self.payload = payload

    # 构造要返回的错误代码和错误信息的 dict
    def to_dict(self):
        rv = dict(self.payload or ())

        # 增加 dict key: return code
        rv['return_code'] = self.return_code

        # 增加 dict key: message, 具体内容由常量定义文件中通过 return_code 转化而来
        rv['message'] = J_MSG[self.return_code]

        # 日志打印
        logger.warning(J_MSG[self.return_code])

        return rv

 

CustomFlaskErr 是我们自己写的处理错误的类,然后通过 @app.errorhandler(CustomFlaskErr) 这个装饰器在 flask 中注册。

具体功能在注释里基本都写了,我们看一下怎么使用这个自定义错误处理器。

# 用户名输入为空
    if user_name is None:
        raise CustomFlaskErr(USER_NAME_ILLEGAL, status_code=400)

 

当需要处理某个错误的时候,rasie 刚才的 CustomFlaskErr,传递另外定义好的自己的错误代码,以及标准的返回代码;

上面说的常量定义文件可以参考如下:

USER_ALREADY_EXISTS = 20001  # 用户已经存在
J_MSG = {USER_ALREADY_EXISTS: 'user already exists'}

 

通过这样的机制,就做到了在具体 restful api 的业务逻辑代码中简单的进行各类自定义错误的处理,所有的错误处理是集中的,细颗粒度的错误代码和消息也是集中维护,便于扩展。

flask 官方文档和一些网上的资料都说比较简单,实践中摸索了这样的实现方式供参考。

(首发简书

女神节

(首发简书

公司从去年开始非常重视文化细节,很多地方可以和优秀外企媲美,企业文化只是口号怎么行,当然要落地,各类节日对员工的关心肯定需要。

员工也不傻,企业是真用心,还是走走形式,也分得清。

女神节,hr很早就开始筹划,然后拍照、打印、在昨天晚上放到每个女员工的桌子上,还要放上小礼物,在公共区域还有照片墙,效果很棒。

企业文化已经谈了几十年,说简单也简单,用不用心自己知道,员工也知道。走形式,哪怕花费再多金钱,不走心,没用。

三月早春

突然发现2月没有在这里写啥文字。一年年时间的确飞快。1月底又去了台北,阳明山、台北故宫、101,或熟悉,或陌生。

第一次去故宫和101,还是2013年11月,记得一行人在垦丁闲逛,当时其实住在新北,现在新北好像算并入台北了。颇为窘迫的是从台北回来的时候,由于一些阴差阳错,差点住的地方都没有。往事虽然略心酸,苦中作乐。

勇于挑战自己,以前有一段时间老想着要留些什么给以后,现在方觉得这样活岂不太累。人生要写意一些,每一刻努力,自然有沉淀,以后的事情想太多也未必有用。

今年春节早,工作上已经进入了忙碌,诸多挑战,压力大,也有趣。琢磨着今年是否要写一本书作为这几年工作的记录,大数据、机器学习、python,似乎都不错。写书的确比较难,选题、文字功力、坚持诸多种种,似乎平时还是积累的略少了一些。

汇付天下第一届科技节

我觉得我们公司不算很大,汇付数据1000人不到,整个集团2000人不到,现在有13个子公司,这几年发展非常快,但是和 BAT 之类相比,真不算大。

今天是公司新大楼好了之后的第一次使用,举办的就是第一届汇付科技节。

我的团队很厉害,夺得唯一的一等奖,还有一个三等奖,虽然我觉得获得三等奖的机器学习项目更有技术含量,不过一等奖的数据门户大家一路做到现在,也着实不容易。

对于数据仓库、hadoop、机器学习等的相关研究,其实都是刚刚起步,还差得很远,继续加油。

学习 python 的可爱的孩子们

又是一个学期,时间真快,自己也不容易,这个学期14节课,风里来雨里去,来回就要1个多小时,坚持下来。今天终于是最后一节课,欢乐的考试时光。

还是希望现在这些条件越来越好的孩子们,可以好好学习电脑,学习编程,成为未来的栋梁之才!

小时候自己主要在中学和少科站,至今不能忘记当年格致中学的励幼娣、周柏生老师,少科站的曹文浩老师,谢谢他们的悉心指点,当年的我也有点像现在这些孩子,聪明、贪玩。很多道理都是后来才懂。

开源内部培训的 python 教程

这几年,作为布道者,始终在探索一些新的知识点,在 python 以及其应用的 restful api、数据统计、机器学习等领域算是略有斩获吧,也更加理解,作为初学者来说,如今的编程领域的确功能强大,但是门槛其实并不低。

在公司内部做了一段时间 python 培训,所以逐步将这些内部培训材料公开出来,目前是最基本的 python basic,也就是 python 的入门教材。

https://github.com/chinapnr/python_study

拙作,欢迎拍砖。希望之后有能力和时间继续各类 python 专题,特别是机器学习、NLP、flask、pandas 和 numpy 等,都非常有趣和功能强大,python 和 js、java 一样,几乎可以胜任任何领域的开发。

2016年11月打卡

这几年,忙到一个月没有写 blog,倒是不太长有。

忽然就12月了,天也冷了,上海就像伦敦,阴雨霏霏。

人生一站一站,余生更要珍惜。

其实11月发生了不少事情,所以这个也算是自己的打卡贴了。