Python 多层 decorator 内获取原始函数参数字典

0. 在 decorator 里获取原始函数的参数值

项目里做了一个通用锁,使用 decorator 来方便的包住某些需要限制并发的函数。因为并发不是函数级别的,而是根据参数来限制,所以需要把参数传到通用锁的 decorator 里,代码大致如下

def lock_decorator(key=None):
    def _lock_func(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            # TODO: get lock_key
            lock_key = kwargs.get(key, '')
            with LockContext(key=lock_key):
                return func(*args, **kwargs)
        return wrapper
    return _lock_func

@lock_decorator(key='uid')
def apply_recharge(uid, amount):
    # ...

考虑到函数调用不一定都是带着参数名的,就是说调用时不一定所有参数都会进 **kwargs,那就需要从 **args 里面按参数名捞参数

怎么能知道原函数的参数名列表,翻各种手册的得知可以用 inspect.getargspec(func) 来搞到,那么上面的 TODO 部分就可以改写如下

            args_name = inspect.getargspec(func)[0]
            key_index = args_name.index(key)
            if len(args) > key_index:
                lock_key = args[key_index]
            else:
                lock_key = kwargs.get(key, '')

自此,一切都很美好

1. 在 decorator 里获取原始函数的调用参数字典

项目里又做了个通用的 Logger,也做成 decorator 往目标函数一套,就可以打印出调用时的入参和结果,大致如下

def log_decorator():
    def _log_func(func):
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            # TODO: get full args
            print('call func [{}] with args [{}] and kwargs [{}]'.format(func.__name__, args, kwargs))
            ret = func(*args, **kwargs)
            print('func [{}] return [{}]'.format(func.__name__, ret))
            return ret
        return wrapper
    return _log_func

@log_decorator()
def apply_recharge(uid, amount):
    # ...

看起来也还好,不过因为函数可能带默认参数,而且也希望看到 **args 到底传到哪个参数上,还是希望把所有参数按 Key-Value 的形式打印出来,跟处理通用锁一样,用 inspect.getargspec(func) 把参数名和默认值都摸出来,再考虑一下可变参数的情况,对上面的 TODO 部分改写如下

            args_name, _, _, func_defaults = inspect.getargspec(func)
            parsed_kwargs = dict()
            # default args
            default_args = dict()
            default_start = len(args_name, func_defaults)
            for idx, d in enumerate(func_defaults):
                default_args[args_name[default_start + idx]] = d
            parsed_kwargs.update(default_args)
            # args with name
            varargs_start = len(args_name)
            for idx, a in enumerate(args[:varargs_start]):
                parsed_kwargs[args_name[idx]] = a
            # varargs
            if len(args) > varargs_start:
                parsed_kwargs['varargs'] = args[varargs_start:]
            # kwargs
            parsed_kwargs.update(kwargs)
            print('call func [{}] with args [{}]'.format(func.__name__, parsed_kwargs))

到这里,还是很美好

2. 多层 decorator 怎么拿到最原始函数的参数表

注意到上面两个例子里,apply_recharge 都只套了一个 decorator,如果两个一起用会发生什么?

根据 PEP318 里对 decorator 的定义

@dec2
@dec1
def func(arg1, arg2, ...):
    pass

等价于

def func(arg1, arg2, ...):
    pass
func = dec2(dec1(func))

这里就出问题了,dec2 拿到的传入函数其实是 dec1 而不是 func。不过在把 lock_decoratorlog_decorator 混用时,不管谁写前面,func.__name__ 都是原始的函数名,说明也还是有神器的地方做了穿透,但是 inspect.getargspec 又拿不到最底层函数的参数表,导致不管谁前谁后,都有问题

注意到每个 decorator 构建的时候都又封了一个 @functools.wraps(func),这个是干嘛的呢?以前都是无脑用,也没想过为啥要包一层这个,去掉会怎样?

去掉这个 @functools.wraps(func) 后,inspect.getargspec 还是一样的只能拿到最近一层的信息,而之前本来可以拿到底层的 func.__name__ 也变成最近一层的函数名了,说明这里做了穿透。那么去看看代码吧

# functools.py

from _functools import partial, reduce

# update_wrapper() and wraps() are tools to help write
# wrapper functions that can handle naive introspection

WRAPPER_ASSIGNMENTS = ('__module__', '__name__', '__doc__')
WRAPPER_UPDATES = ('__dict__',)
def update_wrapper(wrapper,
                   wrapped,
                   assigned = WRAPPER_ASSIGNMENTS,
                   updated = WRAPPER_UPDATES):
    """Update a wrapper function to look like the wrapped function

       wrapper is the function to be updated
       wrapped is the original function
       assigned is a tuple naming the attributes assigned directly
       from the wrapped function to the wrapper function (defaults to
       functools.WRAPPER_ASSIGNMENTS)
       updated is a tuple naming the attributes of the wrapper that
       are updated with the corresponding attribute from the wrapped
       function (defaults to functools.WRAPPER_UPDATES)
    """
    for attr in assigned:
        setattr(wrapper, attr, getattr(wrapped, attr))
    for attr in updated:
        getattr(wrapper, attr).update(getattr(wrapped, attr, {}))
    # Return the wrapper so this can be used as a decorator via partial()
    return wrapper

def wraps(wrapped,
          assigned = WRAPPER_ASSIGNMENTS,
          updated = WRAPPER_UPDATES):
    """Decorator factory to apply update_wrapper() to a wrapper function

       Returns a decorator that invokes update_wrapper() with the decorated
       function as the wrapper argument and the arguments to wraps() as the
       remaining arguments. Default arguments are as for update_wrapper().
       This is a convenience function to simplify applying partial() to
       update_wrapper().
    """
    return partial(update_wrapper, wrapped=wrapped,
                   assigned=assigned, updated=updated)

原来就是这里耍花样了,把底层函数的 ('__module__', '__name__', '__doc__') 都赋给了 decorator 封起来的这一层,欺骗更上层用 __name__ 去判断时就当我是底层

那我也学这个,把 inspect.getargspec 的地方也处理下不就完了,去看看这个地方是怎么拿参数表的

# inspect.py

def getargspec(func):
    """Get the names and default values of a function's arguments.

    A tuple of four things is returned: (args, varargs, varkw, defaults).
    'args' is a list of the argument names (it may contain nested lists).
    'varargs' and 'varkw' are the names of the * and ** arguments or None.
    'defaults' is an n-tuple of the default values of the last n arguments.
    """

    if ismethod(func):
        func = func.im_func
    if not isfunction(func):
        raise TypeError('{!r} is not a Python function'.format(func))
    args, varargs, varkw = getargs(func.func_code)
    return ArgSpec(args, varargs, varkw, func.func_defaults)

看了下用到了 func.func_codefunc.func_defaults,按 Python 官方文档 https://docs.python.org/2/library/inspect.html 的解释,func_code 是运行时的字节码,从这里面捞参数表果然可行,那是不是我把这两个属性也传递上去就行了呢?改用自己的 wraps 如下

WRAPPER_ASSIGNMENTS = functools.WRAPPER_ASSGNMENTS + ('func_code', 'func_defaults')
def my_wraps(wrapped,
             assigned = WRAPPER_ASSIGNMENTS,
             updated = WRAPPER_UPDATES):
    return _functool.partial(functools.update_wrapper, wrapped=wrapped,
                             assigned=assigned, updated=updated)

运行时报错,看了下错误提示,func_code 不可覆盖,这也对,都是运行时的字节码了,这个覆盖掉那包的这层 decorator 到底还有没有自己的逻辑部分

还是自己动手丰衣足食,既然 func_code 不可覆盖,我自己另外弄一个总可以了吧,而且当前需求是拿到参数表和默认参数,那就直接解出来穿透,也懒得最后再解一次。修改 my_wraps 如下

WRAPPER_ASSIGNMENTS = functools.WRAPPER_ASSIGNMENTS + ('__func_args_name__', '__func_default_args__')

def my_wraps(wrapped,
             assigned = WRAPPER_ASSIGNMENTS,
             updated = functools.WRAPPER_UPDATES):
    if getattr(wrapped, '__func_args_name__', None) is None:
        setattr(wrapped, '__func_args_name__', inspect.getargs(wrapped.func_code)[0])
        func_defaults = getattr(wrapped, 'func_defaults') or ()
        default_args = dict()
        default_start = len(wrapped.__func_args_name__) - len(func_defaults)
        for idx, d in enumerate(func_defaults):
            default_args[wrapped.__func_args_name__[default_start + idx]] = d
        setattr(wrapped, '__func_default_args__', default_args)
    return _functools.partial(functools.update_wrapper, wrapped=wrapped,
                              assigned=assigned, updated=updated)

同时在运行时解参数表,也用一个通用函数来实现

def parse_func(func, *args, **kwargs):
    parsed_kwargs = dict()
    # default args
    parsed_kwargs.update(func.__func_default_args__)
    # args with name
    varargs_start = len(func.__func_args_name__)
    for idx, a in enumerate(args[:varargs_start]):
        parsed_kwargs[func.__func_args_name__[idx]] = a
    # varargs
    if len(args) > varargs_start:
        parsed_kwargs['varargs'] = args[varargs_start:]
    # kwargs
    parsed_kwargs.update(kwargs)

    return parsed_kwargs

这样在 lock_decoratorlog_decorator 里,用 my_wraps 来封装处理,同时在里面用 parse_func 来解析参数,就能拿到完整的参数表了

完整的测试代码见 https://gist.github.com/whusnoopy/9081544f7eaf4e9ceeaa9eba46ff28da

cmder 在 Win10 WSL 下粘贴丢字符的解决

Win10 升级到 1803 后,用 cmder 连的 bash,粘贴文本时总丢大量字符,怀疑某些部分被识别成了控制字符或怎样。一开始以为是 WSL 的问题,不过后面交叉验证,发现如果用 cmder 开 Windows 命令行,或直接在 Windows 命令行下运行 bash 就没事。翻了好久,终于在 ConEmu 项目下找到相关讨论,作者最近认可了这个问题并发布了更新:https://github.com/Maximus5/ConEmu/issues/1545#issuecomment-386444227

因为 cmder 就是封装了一下 ConEmu,所以去 https://github.com/Maximus5/ConEmu/releases/tag/v18.05.06 下载最新的 180506 版本 ConEmu,并解压到 cmder 目录的 cmder\vendor\conemu-maximus5 下替换原来的文件就好

莫莫两岁啦

体检归来,身高 85.5,体重 10.7,长牙 16 颗。身高还是中下水平,大概 30 分位,体重半年才长了一斤,都掉到 15 分位下了,但是吃的也不少,品类也挺繁多的,果然还是运动量太大么,本来爸爸看长 18 颗牙的,在社区体检看还是 16,最近总不好好张开嘴给看,估计是之前臼齿两头冒尖被误认是两颗了?

小朋友大一些了就各种小心思,出去玩偷懒不想走,非得要抱,到地方了就下来疯跑捉都捉不住,在家有事没事嗲嗲的叫「爸~~爸~」「妈~~妈~」,然后过来求个抱抱或想能不能赚点饼干或糖

占有欲更强,在外面总要疯跑无意撞到别的小朋友或故意推开,每天回家都听到的是「今天又欺负了几个小朋友,把几个小朋友弄哭了」,希望这个暴力期快点过去吧。有时候嘴里会咕哝「摇来摇去摇不倒」,这是把别人当不倒翁了么,自己倒是平衡性维持的很好,经常踩到东西或看着要滑到,但摇摇晃晃又能调整过来

能更自由的用语气词,各种自夸,爸妈下班回来帮拿拖鞋后自己来一句「宝宝真能干」,自己想看 DVD 时麻溜的自己打开,然后来一句「宝看一集这个吧」。记忆和表达能力更好,妈妈回家都可以跟妈妈聊起来,今天去了哪里,干了什么事情,和哪些小朋友玩了啊

出去玩会很鸡贼的注意别的家长或小朋友手里的吃的,然后故意装傻跑过去问「这个是什么呀」,遇到好心的奶奶给分吃的,一边说着「宝就吃一个」,另外一边又把空着的手伸出去「这个手还没有」

早上起床时间相对固定在八点五十左右,晚上睡觉还是看白天有没有玩的很疯和有没有睡,如果白天没睡,晚上一般八九点就吃奶睡了也挺好,如果下午有睡两个小时,那晚上没有十一点都难整睡着

现在一天吃的典型节奏是,起床后吃冻鸡蛋、喝粥,上午吃一点水果,中午正餐吃米饭配菜,下午吃一点水果,晚饭吃面条,到晚上八点左右再补一小顿白米饭,睡前喝 200ml 的奶,早上五六点喝 200ml 的奶。喜欢吃鱼,对肉还是不太感兴趣,面条一般熬点排骨汤什么的做汤底

目前还是穿尿不湿和拉拉裤,前阵子天气还有点冷,没在训练自主排便,外婆他们倒是挺着急说这么大了还不会自己上厕所,以后上学了怎么办,这个,也还好吧,小朋友大了自然就会的,顺其自然。拉臭了会主动说「宝在拉臭臭」,然后等换洗,尿尿了一般没有主动说,但是如果太多了会自己抓下提醒带的人。有害羞的意识,在外面给他换尿不湿要扯他裤子都不让扯,感觉有时候出去玩他也有点故意憋尿憋臭,怕在外面给他换?

快两岁时跟妈妈合影

快两岁时跟妈妈合影

莫莫快两岁

最近莫莫爸爸忙和懒了好多,记录没有及时跟上啊

年前莫莫快二十二个月的时候,被染上流感,小家伙烧的一塌糊涂,还好及时去医院确诊流感,妈妈想办法弄到达菲,春运期间的票不好改,伯伯和姑姑帮一起带回老家,在奶奶家过的整个春节

年后回到杭州二十三个月过了没多久,又有一次突然发烧,后面去医院被诊断为肺炎,住院几天才好

因为最近两次生病,一直去医院抽血检查和在家喂药,现在对医院和医护人员特别敏感,见到就哭闹,小朋友还是健健康康不要去医院的好

吃喝拉撒睡没有什么太特别的变化,吃的东西更杂,但是经常也犯懒要喂,变得更馋,看到大人吃什么都想过去分一口,白天基本都不睡了,晚上从八九点睡到早上八九点

语言和思维能力是最近进步的最明显的,除了有点奶声奶气发音不准,很多事情已经可以很清楚的表达,成天自己咕哝咕哝说个不停,好多大人都听不懂,对一切事物充满好奇,会问这是谁这是什么这个在干什么这个怎么了

记忆力总在不经意间表现的让人吃惊,春节期间有一次随口问了下他爷爷叫什么名字,然后一路顺着把爷爷奶奶外公外婆爸爸妈妈名字都说对了,日常有时候随口说的话也能被他记住,放什么东西更逃不过他的眼睛

脾气大部分时候更温和,但偶尔也比较极端,出去玩的时候有占有欲,不让别的小朋友玩自己的东西,自己占住的地盘也不想别人来,会推别的小朋友,搞的小区好多小朋友被欺负哭过,后面见到就躲,这是要变熊孩子的节奏么?

能自己玩,虽然对同一件东西的专注时间还是不够长。自己摔倒或有别的丢人事情时,不喜欢别人关注,不然会觉得好出丑,甚至恼羞成怒

早上睡起来不再有哭哭闹闹起床气,而是会高兴的说「早上好」。爸爸妈妈下班回来都会帮忙拿拖鞋,小暖男啊

理性认知相对一般。数字能数到二十,但是还没多大概念,问他什么东西有几个或有多少,统一回答「二十个」。颜色应该能分清,但是总不按大人期望的方式回答。对文字数字认识一般,偶尔会按刚教的用强大记忆力复述,但是不像是自己完全学会的样子

肺炎住院时妈妈请假陪了几天,现在跟妈妈的关系明显变好,愿意跟妈妈在一起玩,也会想黏妈妈,不再像某一段时间老是不要妈妈

坐车已经完全接受了安全座椅,现在坐安全座椅或自己童车,会主动要求拉安全带,坐车变得容易睡着,经常上车时很兴奋,路上就睡着了然后抱着下车放床上继续睡


一些有意思的片段

在老家爷爷奶奶带,有一次爷爷问「莫莫是不是小馋猫」,被反口一句「叶文是大馋猫」呛回来,这家伙,啥时候学会直接叫名字也学会这么反呛的

在老家,爷爷叫奶奶或奶奶叫爷爷有时候喊名字对方没听见,莫莫会帮忙用名字大叫,而不是叫「爷爷」或「奶奶」,回杭州后有时候对爸爸妈妈也这样

自学成才,知道在地上打滚撒泼了,更好玩的是在家里不管一开始在哪里,总要跑到垫子和地板中间的位置,上半身趴垫子上,下半身在地板上打脚,这样是即可以打的地板啪啪响吸引注意力,又避免趴地上太凉么?

WSL 下一些奇怪的路径依赖问题优化

在公司换用 Windows 做开发机,装了 Windows Subsystem for Linux(WSL),也就是那个 Ubuntu,用来跑开发环境

我的代码放在 Windows 的文件系统里,在 WSL 里通过 ln -s /mnt/c/foo ~/foo 的方式映射过去,不过在跑 yarn 装 node modules 的时候,会经常出现路径依赖的错误,大概就是 /mnt/c/xxxxx 这样的路径在计算父目录或子目录时会出问题

另外我跑 Docker,是使用 Docker for Windows 作为宿主,在 WSL 里装 Linux 的 Docker 客户端做控制,跑 docker-compose 总是发现挂载不上开发目录到文件系统,最后看了下是 WSL 默认的 /mnt/c/ 这样的挂载点识别有问题

最后按某些野路子方法,把 WSL 访问宿主机的入口调整为 /c/ 这样就好了

$ sudo mkdir /c
$ sudo mount --bind /mnt/c /c

不过这有个问题是重启后需要重新挂载,之前有按别的一些处理方式写到 /etc/fstab 文件表里,但是 WSL 不支持自动加载,所以按 https://nickjanetakis.com/blog/setting-up-docker-for-windows-and-wsl-to-work-flawlessly 的提示来加到 ~/.bashrc 里或我的 ~/.zshrc 里,并把 /bin/mount 改成所有用户都可启用

$ echo "sudo mount --bind /mnt/c /c" >> ~/.bashrc && source ~/.bashrc
$ sudo echo "yourname ALL=(root) NOPASSWD: /bin/mount" >> /etc/sudoers

注 1:yarn 的问题似乎现在在 /mnt/c/foo 这样的目录结构下工作正常了,不确定是不是 yarn 升级处理了这个问题

莫莫二十一个月

语言能力继续突飞猛进,脾气变得极端了不少

单独给莫莫做吃的后,还是会喜欢坐大人腿上看大人吃饭,要自己拿筷子戳戳戳,到后面演变成帮大人夹菜,虽然经常是戳到桌子上,但大部分时候还是挺像模像样的,就是会出现弄太快来不及吃,或者他一直催「爸爸吃这个吃这个」

吃饭时偶有坏习惯,突然想起来把嘴里吃的这一口吐掉,也没有明显的逻辑,可能就是单纯贪玩或不想吃,因为前后吃一样的东西都吃的好好的。吐还会找墙角地板什么的吐,被口头教育后稍微好一点,大部分时间还是喂饭的跟着注意到迹象后直接拿餐巾纸接住

午睡从可以在家哄睡着,变成要坐着童车去小区里兜一圈才能睡着,到十二月底推车出去兜圈也没用了,绝大部分时间变成中午不午睡,然后晚上七八点自己主动要睡觉。到一月份后,经常是晚上差不多到点了,自己急了跳脚「吃奶奶吃奶奶」然后很快「睡觉觉睡觉觉」,往手上一靠直接睡着。半夜睡的还是偶尔醒一下要哭哭抱一会,早上被闹醒了也会很不开心,而且没清醒过来前,哭闹是止不住的,说话完全听不进去

起床气越来越明显,起床后多半需要看上一首儿歌或贝瓦儿歌里面别的什么,才肯配合穿衣出来

四颗虎牙都出来了,目前十六颗牙都长的不错,也比较整齐,但是现在不太给看了,说过来给爸爸给看看牙,都是要立马跑开。从完全抵制刷牙到偶尔愿意刷牙,不过大部分时间还是自己叼着牙刷玩,还要担心是不是玩水把衣服弄湿

喝水偶尔有坏习惯,最后叼着水杯不放,还要跑来跑去,磕过几次也不长记性。另外偶有几次喝到后面嘴里含一口,等水杯拿开后自己吐出来玩,容易把衣服裤子弄湿

开始有点电视迷,会要看电视上的动画片或儿歌,要不就是手机上的。会主动粘着要开电视,跟他把遥控器藏起来,会自己摸开电视机上的物理开关。哪怕把电视的网络断掉,跟他说电视坏掉了,也还是会要看手机上的。家里不同人的手机,都可以准确找到贝瓦儿歌的 App 并打开看

变得更黏爸爸,早上起来陪玩后都不让去上班,以前说再见后开门走人已经不行了,要偷偷走才行。吃饭也不让爸爸好好吃,非得先陪着玩,等伯伯和妈妈吃完换人陪玩时爸爸再去,就这样还是有可能吃到一半被拉走要陪玩积木或他觉得只有爸爸会的东西

莫莫游泳

莫莫游泳

亲亲变得有些敷衍,凑近了嘴巴咂一下就算,才不管是否亲到脸。而且只亲爸爸,妈妈求亲亲多半都不理,伯伯天天带着也不亲,这是因为爸爸有事没事就缠着莫莫要求亲一个,加上都是男生的缘故么

不愿意黏妈妈,经常妈妈回来一开门就开始喊「不要妈妈」,弄得妈妈可伤心了。小朋友还是要多陪伴,带的多的还是会更黏一些,元旦后妈妈去余杭妇保下乡,爸爸也早起开车送妈妈,少了早上的亲子时光,跟爸爸也没有之前那么黏

妈妈给买了本百科全书,异常喜欢驯鹿,每天都要拉着爸爸去找驯鹿在哪里,而且还说「妈妈不认识」「伯伯不认识」,非得拉爸爸去才行

脸上高原红一般的开裂状况变好,用丝塔芙比较厚重的面霜多擦擦还是保湿一些,现在粉嫩粉嫩的,可爱到随时想咬一口。不爱洗脸和擦粉,都要连哄带骗分散开注意力再上手去弄他,不过洗手倒是挺主动,经常主动把手伸出来要用湿毛巾擦,而且会主动换手

胆子越来越大,之前都会老老实实呆在厨房门口,现在敢跑进去了。而且进去多半都是在捣蛋,要么把扫把簸箕弄出来说要扫地,要么把橱柜拉开把面条什么的弄到客厅,撒的到处都是。茶几抽屉里有几包爷爷种的花生,经常要求打开拿出来抛的满屋都是,大人在家走路什么的经常都要注意着点,一不小心就可能踩到莫莫布置的地雷

说话奶声奶气,把全家都带偏了,天天「在哪里zai1na2li4」「什么shen2mo4」。而且会自己表达超多的情绪,知道自己是「莫莫宝宝」,有时候需要表达第一人称,会说「宝宝怎样怎样」。带他去商场,伯伯和妈妈去试衣服,售货员阿姨逗他说要抱抱,莫莫不要,还来一句「宝宝不好意思」,笑翻全场,不知道是不是前面爸爸带着在扶梯上说亲一个,莫莫没亲爸爸问「是不是不好意思」然后记住了

自己用积木堆小火车

自己用积木堆小火车

看过的书还是会记住的,自己淘气把凳子拿出来放倒摆客厅垫子上,然后跑到一边半蹲说「拉臭臭」,再跑到另一边把手伸出去说「洗手手」,完了再来一句「拉完臭臭真舒服」,本来大家还奇怪好像并没有教他这些,特别是最后一句,后来发现之前看的「好习惯绘本」里关于「拉臭臭」那本书,最后小熊就是这么说的

会有点小心机,之前问他「谁是小馋猫」,他会很老实的承认「莫莫是小馋猫」,现在变成了「爸爸是小馋猫」,小坏坏的。拉着爸爸给他看动画片,还会说「这个不好看,爸爸换一个」。自己轻微撞到或碰到,一般就跟没事人一样,但是有大人跑去关注的话,就要开始撒娇一下。假哭越来越像真的了,经常一言不合就嚎起来,同时豆大的眼泪立马滚下来,让人心疼,不过判定他是假哭的话又好笑,当然是不好说他假哭的,他要被揭穿了可能就伤心恼怒变真哭了

天不怕地不怕的活跃分子,带来的结果之一就是额角上总是有包,从来就没好过,上一次的快好了一定会撞出下一个包来,都跟他开玩笑说头上长了两只角了。莫莫还不太理解头上的「角」,经常开玩笑问他长角了,他立马蹲下去摸自己的脚表示脚在这里

爸爸去日本,在大阪环球影城带了一只 Snoopy 玩偶回来,还是没法冲抵对兔子的喜爱,睡觉什么的还是要抱着自己那只兔子,现在问兔兔叫什么,已经起名叫「妮妮」了,并且也会交替用妮妮和兔兔来称呼之

妈妈在努力教一些简单的英文,苹果、葡萄、桃等能记住也能复述。对数字和颜色还是不敏感,能从一数到十,但是更多是用背书那种方式来背出来,还没有明确的数字和大小概念,跟他好好讲又淘开

隐藏 HP 打印机在 Win10 下无法安装的驱动更新

公司使用的打印机是 HP 的 1536,很经典的一款,但是也有一个很头疼的问题,就是在 Windows 10 下,会总是提示会有驱动升级,名称是 HP driver update for HP LaserJet M1530 MFP Series PCL 6,但是从来都无法安装成功

看这个事情很不爽,但是一直也没有找到很好的解决办法,HP 官方论坛和微软的官方论坛里都没有合理的解决,有提议把驱动卸了就不会出更新提示的,但是,卸载了驱动我还怎么打印

好在今天搜到一个 Win10 系统禁止某一更新 的方法,实测解决,原文请点左边的链接进去,我这里简单重复

  1. 去微软官网下载 wushowhide.diagcab
  2. 运行,在 Hide Update 里勾选不想要的更新,解决

2018 新年快乐

给自己看的 2017 个人总结并没有写,连提纲都没有,一年比一年懒

2017-2018 在日本大阪跨年,其实是睡过去的。2018 第一天在大阪环球影城,本来打算老年观光游,结果浪到飞起

新的一年,新的开始,新的征程,加油

莫莫二十个月

最明显的变化就是语言表达能力真的进步了好多,大部分时间已经可以无障碍沟通了。还是按吃喝拉撒睡玩长来说

奶粉从国版爱他美 3 段换成德版爱他美 1+ 段,没啥特别的考虑,就是觉得德版现在用的纸盒变得方便后,配方影响应该也不大。德版的勺子变宽变深了一些,往标准口径奶瓶倒的时候容易漏出去,不过 180ml 的水也只要四勺了。晚上可以不用吃了,早上偶尔要在六七点吃一顿奶,或者就等睡醒再吃,会对睡眠质量好点

之前一直用小奶锅给莫莫单独煮吃的,发现水煮的做法现在经常不爱吃,更爱吃大人的菜,就另外买了一口锅,也是用跟大人一般的炒法来做,只是油盐等放的更清淡。吃东西经常第一口要说「烫」,明明很多时候已经吹冷了的,另外自己对烫的东西也会学着吹吹吹

小馋猫一只,只要看到爸妈吃东西,横竖要凑过去也想来一口,各种水果基本都吃过了,经常自己看到餐桌上有水果了会跳着脚说「吃橘橘」「吃甘蔗」。不过也是小懒猫一只,经常吃的东西自己不想拿,要爸妈拿着喂

喝水时经常变身小水牛,能一口气喝掉保温杯一大半,不过自己要是不想喝,也会直接把杯子推开

秋天的时候经常尿一大泡,尿不湿没有拉拉裤兜那么多,双十一时买了很多拉拉裤。但冬天了拉拉裤就没有纸尿裤方便,换的话要把整个裤子拔掉,如果不是拉臭要洗屁股,一般就换尿不湿了,晚上睡觉用拉拉裤,跟一开始的设计想法不太一样啊。另外换尿不湿的频率变低,现在一天也就六七次的样子

天气冷了就开始睡懒觉,早上要睡到八九点才起来,放开让他睡估计到十点都能睡,不过怕早上睡太多下午和晚上不好睡,一般也还是八九点等他哼哼唧唧进入浅睡眠后把他叫起来。下午睡的更晚,一般要到两三点,不过还是要睡够两个小时以上,不然起来有很大的起床气,一直哼哼唧唧哭哭啼啼怎么哄都不行,得过上一两个小时才自己好。晚上也越来越晚,经常要搞到快十点才睡,等睡着估计都十一点了。家里把作息都调到跟他一致,晚上都弄比较晚,偶尔也会自己主动要求提前睡,八九点突然喊要喝奶奶,然后就很快睡着了

除了兔兔,现在睡觉要带更多的玩具一起,有巧虎的手偶,有小猪佩奇(其实是佩奇的弟弟乔治),如果没搂着一起睡,可能睡着后过一会就要哼哼唧唧「要兔兔要兔兔」。半夜偶尔也突然迷迷糊糊把兔兔拽过去蹭一蹭,再被拍拍接着睡

四颗虎牙出来了三颗,另一颗也鼓起来蠢蠢欲动,后面的槽牙不太看得见,应该还没出来。变得不要刷牙,怎么哄和强迫都没有用,只能在他吃奶后喂点水靠漱口解决

认识了更多的动物、水果、蔬菜,日常生活中的好多东西都认识,也能说出来。语言能力从短句变成更长的复杂长句,比如「妈妈坐公共汽车去上班」「爸爸开小汽车接妈妈」,自己要什么和不要什么也可以更好的表达,拉臭臭了问他会点头,或者自己主动说「拉臭臭」,然后还要「爸爸打水洗屁屁」

会背好多唐诗和儿歌。一开始是会背咏鹅,有好些字发音还不准,但是能听出来他就是在背,背完「拨清波」还要自己鼓掌一下,然后会了「悯农」和「静夜思」之类。儿歌则更简单一点,四句或六句,有一本儿歌小册子基本都会了,好一些爸爸妈妈都不记得或记错了的,莫莫自己都毫无压力完整背出

要看手机看电视,已经能分出好多动画片,会有自己的想法去看,给莫莫的 iPhone 5 各种无压力解锁,自己点开贝瓦儿歌看视频听儿歌,后来看他实在太流畅也管不住,只能把手机密码改掉,这样才算是压住不停看电视的上瘾儿童

莫莫十九个月

前篇说十八个月大部分事情记混了,主要是最近弄病了一场,全家都折腾的够呛

国庆节前后奶奶来杭州了,然后国庆假的时候伯伯回去了一周,爸爸带睡,除了前一两天还有点想伯伯,大体都好

大概 10.6 半夜吃奶完拉了一次臭,从那天开始,一天一次臭就变成了一天三到五次,这时候还好都没拉稀,就只是次数变多,家里人分析应该是红薯吃多了,每天晚饭吃完再吃点奶奶从老家带来爷爷种的红薯

10.14 周六奶奶回去的那天开始,拉臭就变拉稀了,连着去社区医院看了几次,也都没特别好的解释,说病毒感染,开「蒙脱石散」控制拉肚子,「头孢」消炎

拉肚子没好,持续到 10.19 周四开始偶有发烧,周五晚上爸爸去小区门口买了「泰诺林」和「美林」回家配合年初去日本买的「退烧贴」降温

都没见好,等 10.21 周六去社区医院看说建议去同德,另外抽血检查还是说病毒感染,拉肚子有好点,停「蒙脱石散」换「妈咪爱」调节肠胃,继续吃「头孢」消炎,血色素有降挺多,扎手验血时手都惨白惨白的,连着吃不好睡不好虽然很能闹还是影响精神了。依然半夜就烧一次 38.5 以上的,白天就还好,下午睡觉也会烧一下。本来拉肚子好挺多了,周六晚上为了缓解感冒症状烧了点葱根水喝,立马又退回到一天三五次的拉稀状态

10.23 周一去滨江省儿保,排了两三个小时队才看上普通门诊,又抽血这次也没看出啥特别的,把之前的药都停了,换「酵母素」调节肠胃加某缓解咳嗽的滴剂。其实去儿保那天发烧基本就没有了,后面也没再复发,看着就是季节性感冒发烧一周自愈的节奏

拉肚子持续到 11.3 周五左右基本算好了,不发烧后感冒的症状一直没太好,流鼻涕和咳嗽,所以 11.3 又去社区医院看了下咳嗽的症状,也没说出个所以然,另外有开药吃。莫莫折腾了这么个把月,从之前对医院无感甚至还乐呵呵的变成了极度恐惧和抵触,扎针也非常害怕,到现在去医院在大门口就不愿意进去。回家吃了两天后发现有一种药就是我们老家生产的,全家的态度立马都是「这玩意儿靠谱么。。。」,我们家到底是不发达到什么程度才让大家都这么不信任

莫莫不舒服这段时间,晚上睡的都不好,经常醒,可能也跟白天摁住喂药哭惨了有关,导致带睡的伯伯也长期睡不好,爸爸睡隔壁书房帮晚上起来冲个奶啥的,后面也没用了,就是要伯伯抱着睡,安全感的缺乏啊。晚上抱着睡和白天午睡越弄越晚,连着把家里人都给整感冒了,先是伯伯再是爸爸,本来周末说妈妈不要去看业余门诊了回家帮带娃吧,周五晚上妈妈也感冒了,一家子病号

说过这么多不开心的,还是记录下莫莫开心的成长

十八个月去体检,10.5kg 重 81.5cm 高,本来医生想说我们还是偏矮偏瘦,但一看上次的结果说最近长的还挺多嘛就没多说啥了。在往平均水平在赶,从大概 15 分位到 40 分位的样子,不过后面这一个月整的,估计又要退步不少

语言能力突飞猛进,本来国庆节时担心会不会去体检都会判说不够十个字,没想一下子就从蹦几个字变成了说四五个字或更长的短句(诸如「妈妈不要吃鸡蛋」),再到能有逻辑的表达自己的需求(诸如「要吃奶奶」「爸爸冲伯伯喂」),然后到月初爸爸抱着帮捡东西时都会说「谢谢爸爸」这样的社交礼仪。大部分词汇都没有问题,只要大人慢一点说,都能很容易的复述出来,只是有些音还发不准,毕竟还是奶声奶气的小朋友啊

对数字字母等还是没兴趣,但是他的很多书又能分清什么是什么,一大摞书问他某一本他能精确找出来,还能拿着某几本书说书的名字,是认字了难道?没有刻意教莫莫什么,让他自己成长就挺好的

有小脾气,有时候笑他童言童语或别的小逗比,会生气会不高兴,还会跑过来叫你不要说甚至打脸。小小的人哪心思一点也不小,还是应该平等的当普通人来对待,而不是当一个懵懂无知的小朋友来看

喜欢看电视,经常起来就缠着要看电视,干脆把小米电视续了一年会员并且买了一年儿童会员。手机已经可以轻松解锁自己放贝瓦儿歌,连持续放一段时间后提示休息的童锁也能自己解开,这童锁还有个屁用啊。。。贝瓦儿歌里好些内容还是 VIP 独享,又充了一个会员

喜欢看爸妈在绘图板上画画,有时候会指定内容,比如要爸爸画巧虎书上的蜗牛妈妈带三只小蜗牛,自己会随便划拉,并有刻意想画个鱼出来

对妈妈去年买的 KellyCat 那个兔子爱不释手,睡觉必须要抱着睡,睡到一半翻个身啥的经常还要拍拍兔兔,白天也经常要拎着一起,没事就跟兔兔亲亲(真的不是变成擦鼻涕?)

自己吃完饭后喜欢坐在妈妈或爸爸腿上看爸妈吃,还不停的要催吃菜,急了还会帮忙用筷子或勺子喂爸妈,偶尔自己馋了也要夹大人的菜给他吃,吃的可开心。也开始要自己吃饭,给把勺子自己乱戳戳然后往嘴里送,会弄的到处都是,但小朋友自己学吃饭就是这样过程吧

还是风一样的男子到处跑,字典里压根就没有「慢点」两个字,虽然带他的人天天跟他说「慢点慢点」。没事在家摔多了,前几天妈妈中午带下去哄睡,还是不睡要下地到处跑,最后摔的额角和鼻子都破皮了。妈妈给买冬天在家穿的鞋,买了两双最后还有点大,发现好像是量脚时没注意卷尺的开始数的地方其实已经是 1cm 了,爸爸表示你这效率太差还是我来,严格按脚长买的又有点挤,又退掉重买,最后两个人买了四次才买到一双合脚的,大一点的那双也没退,留着换着穿和过一段脚长大后用

冬天了洗澡总是一开始不愿意进去,前阵子感冒后期给他泡澡,又变泡的不想出来,之前的澡盆有点浅,另外换了个泡澡桶,这下可以舒服暖和泡着了。为了哄好好坐着洗澡而不是站着着凉,小鸭子什么的洗澡玩具也都用上也能玩起来了,现在洗个澡,盆里会有好多东西

对公共汽车情有独钟,没事就在家念叨公共汽车,跟他讲是的妈妈是坐公共汽车去上班的,周末去超市买了个玩具大巴车,能很快就分清这个是「大巴车」不是「公共汽车」。两天内爸妈一起给买了三辆玩具车,加上之前奶奶某次买了一套消防局系列,家里现在一堆玩具车,男孩子还是喜欢车的,妈妈还念叨「我们是不是太宠娃了」

莫莫和玩具们排排坐

莫莫和玩具们排排坐