Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

获取结算单明细时GBK解码错误 #62

Closed
ChnMig opened this issue Sep 16, 2021 · 3 comments · Fixed by #65
Closed

获取结算单明细时GBK解码错误 #62

ChnMig opened this issue Sep 16, 2021 · 3 comments · Fixed by #65

Comments

@ChnMig
Copy link

ChnMig commented Sep 16, 2021

你好, 我在测试使用 ctpwrapper 的 获取结算单明细回调 OnRspQrySettlementInfo 时, 发现回调的多条数据中, 有一些报错

Traceback (most recent call last):
  File "ctpwrapper/TraderApi.pyx", line 1402, in ctpwrapper.TraderApi.TraderSpi_OnRspQrySettlementInfo
  File "/root/python/futures/trader_main.py", line 149, in OnRspQrySettlementInfo
    print(pSettlementInfo.Content)
  File "/root/python/futures/.venv/lib/python3.9/site-packages/ctpwrapper/base.py", line 28, in __getattribute__
    return value.decode("gbk")
UnicodeDecodeError: 'gbk' codec can't decode byte 0xd2 in position 499: incomplete multibyte sequence

这是因为内置函数

    def __getattribute__(self, item):
        value = super().__getattribute__(item)
        if isinstance(value, bytes):
            return value.decode("gbk")
        else:
            return value

在获取到bytes时使用gbk解码, 解码出现了问题, 我修改了源代码为

    def __getattribute__(self, item):
        value = super().__getattribute__(item)
        if isinstance(value, bytes):
            return value.decode("gbk", errors="ignore")
        else:
            return value

设置decode时忽略解析错误的字符来规避错误, 在测试过程中也没有发现数据丢失或错误的情况, 同时也保证了程序正常运行
你是否能将其修改发布? 或者说有更好的解决办法? 这是一个非常好的模块, 给予了我很大帮助, 谢谢!

@nooperpudd
Copy link
Owner

create pr, tbd.

@ChnMig
Copy link
Author

ChnMig commented Sep 17, 2021

创建 pr, tbd 。

我在调试后发现问题的原因是: 当获取结算单时, 交易所将很长的结算单转成bytes后切片发送, 每个切片的长度为500, 而在切片时, 很有可能出现一个文字被切分在上一个切片的末尾和下一个切片的开头, 这两个切片都是不完整的数据, 而每次调用__getattribute__ 会将本次切片的内容解码, 因为不是一个完整的中文, 所以会触发解码失败, 导致错误.
粗暴的只忽略错误是不好的, 这样会导致数据的丢失, 我希望能在等待切片全部传送完成, 组装成完整的获取数据之后再进行解码, 因为 ctpwrapper 封装的比较底层, 可能你不希望逻辑由模块本身处理, 而是由开发者自行处理, 那么我们可以给类 Base 建立一个新的方法, 这个方法的作用是获取这个key的原始数据, 他有可能是bytes

    def get_raw(self, key):
        """
        :return: key的原始数据
        """
        return super().__getattribute__(key)

由开发者自行通过其他的方式, 比如nRequestIDbIsLast 结合来判断和组装数据, 在外部自行解码, 他的调用像这样

pSettlementInfo.get_raw("Content")

如果你同意, 我将重新提交PR

@nooperpudd
Copy link
Owner

需要重写,去掉bIsLast 和 request id, 简化代码。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants