• Python 随笔两则


    1. Python 2 None 对象无 __eq__ 方法的原因分析

    Python2.7: typeobject.c 里面 PyBaseObject_Type 结构体 tp_richcompare 成员为 0
    而在 Python 3.x 的代码里面这个成员的值是 object_richcompare
      
    当 attr 的查找进入 __getattr__ 中,Python 按 __mro__ 来依次寻找,None 的 __mro__ 是 (NoneType, object),在 C 实现中,前者是 PyNone_Type,后者是 PyBaseObject_Type 。这两个类的 __dict__ 中都没有 __eq__ 这个 key,所以查找失败,raise AttributeError.
      
    但是 object.__eq__ 却又能成功,那是因为 object 的类型是 type ,type.__dict__ 中就有 __eq__ 这个 key。有点绕。但通过这件事可以知道 NoneType 是一种“特殊”的类型。

    2. Python 2 终端、文件编码问题

    在交互式命令模式(Interactive shell)下:

    >>> import sys
    >>> sys.stdout.encoding 

    在 Windows 下,如果你的系统是简体中文,一般输出会是 cp936

    >>> import codecs
    >>> codecs.lookup('cp936').name
    'gbk' 

    这就是在 Windows 终端里面使用的编码。在 print 的时候,无论字符串源采取什么样的编码,最终输出的字符串的编码必须跟 shell 的编码一致,也就是说:

    >>> print some_string 

    Python 会做这样一个动作:

    codecs.encode(some_string, coding, errors='strict') 

    当 some_string 是一个 unicode 字符串,coding 是 gbk, some_string 里面包含 gbk 字符集里面没有的字符,Python 就会抛出一个 UnicodeEncodeError.
      
    对于输出到文件中情况是类似的,Python2 的 open() 函数不会传入 encoding,以 'w' 方式打开文件,如果写入 unicode 字符串,Python 会获取当前默认的编码,然后以此种编码把字符串写入文件。可惜的是,“默认编码”只是 Python 自己默认的,在 Objects/unicodeobject.c 中,用一个全局变量 unicode_default_encoding 来表示默认的编码:

    /* Default encoding to use and assume when NULL is passed as encoding
        parameter; it is initialized by _PyUnicode_Init().
      
        Always use the PyUnicode_SetDefaultEncoding() and
        PyUnicode_GetDefaultEncoding() APIs to access this global.
      
    */
    static char unicode_default_encoding[100 + 1] = "ascii"; 

    这个值在 Python 中有C接口(PyUnicode_SetDefaultEncoding)去改变, Python 层的接口:

    >>> sys.setdefaultencoding(coding)

    但需要在编译时增加 Py_USING_UNICODE 宏的定义,官方发布的 Windows 版本没有这个功能。

    所以在调用到类似 file.write(some_string) 的时候,首先会有这样的编码过程:

    codecs.encode(some_string, coding, errors='strict') 

    当 some_string 是一个 unicode 字符串,并且包含 ascii 字符集不存在的字符时,就会抛出一个 UnicodeEncodeError。
      
    所以,为了解决这个问题,可以这么处理:
    (1) 在 Windows shell 下面:

    >>> print some_string.encode('gbk', errors='ignore') # replace 也可,只要不是 strict 

    (2) 在写入文件时,两种方法:
        a. 忽略不存在的字符,同(1)

    >>> f = open(filename, 'w')
    >>> f.write(some_string.encode('gbk', errors='ignore')

        b. byte 方式写入:

    >>> f = open(filename, 'wb')
    >>> f.write(some_string.encode('utf-8'))

    a 会损失字符,b 不会。

  • 相关阅读:
    用jmeter通过ssl验证访问https
    github jekyll主题
    JMeter中返回Json数据的处理方法
    使用Nginx实现反向代理
    Antd 表格 -- 自定义合并行处理
    Go语言--第8章 包(package)
    GO语言 -- 第7章 接口(INTEFACE)
    GO语言--第6章 结构体
    PHP--相关扩展安装
    Go语言--第5章 函数
  • 原文地址:https://www.cnblogs.com/zhangbaoqiang/p/4791377.html
Copyright © 2020-2023  润新知