繁体   English   中英

使用非 BMP 字符引发错误会重新启动 shell

[英]Raising error with non-BMP characters restarts shell

我正在编写一个 python 模块,用于在 pygame 中显示和输入表情符号。 这意味着我经常使用非 BMP Unicode 字符,显然 python shell 不喜欢。

我制作了一个自定义的类似字符串的对象,通过将表情符号序列存储为单个字符来更轻松地处理表情符号字符和序列。 然而,虽然我希望 str(self) 返回对象的原始 Unicode 表示,但这会在尝试打印时导致问题,或者更糟糕的是,当它包含在错误消息中时。

这是错误消息中包含非 BMP 字符时发生的情况的示例。 在 Windows 10 上运行 Python 3.7.3。

>>> raise ValueError('Beware the non-BMP! \U0001f603')
Traceback (most recent call last):
  File "<pyshell#0>", line 1, in <module>
    raise ValueError('Beware the non-BMP! \U0001f603')
Traceback (most recent call last):
  File "<pyshell#0>", line 1, in <module>
    raise ValueError('Beware the non-BMP! \U0001f603')
Traceback (most recent call last):
  File "D:\Python37\lib\idlelib\run.py", line 474, in runcode
    exec(code, self.locals)
  File "<pyshell#0>", line 1, in <module>
Traceback (most recent call last):
  File "D:\Python37\lib\idlelib\run.py", line 474, in runcode
    exec(code, self.locals)
  File "<pyshell#0>", line 1, in <module>
ValueError: 

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "D:\Python37\lib\idlelib\run.py", line 144, in main
    ret = method(*args, **kwargs)
  File "D:\Python37\lib\idlelib\run.py", line 486, in runcode
    print_exception()
  File "D:\Python37\lib\idlelib\run.py", line 234, in print_exception
    print_exc(typ, val, tb)
  File "D:\Python37\lib\idlelib\run.py", line 232, in print_exc
    print(line, end='', file=efile)
  File "D:\Python37\lib\idlelib\run.py", line 362, in write
    return self.shell.write(s, self.tags)
  File "D:\Python37\lib\idlelib\rpc.py", line 608, in __call__
    value = self.sockio.remotecall(self.oid, self.name, args, kwargs)
  File "D:\Python37\lib\idlelib\rpc.py", line 220, in remotecall
    return self.asyncreturn(seq)
  File "D:\Python37\lib\idlelib\rpc.py", line 251, in asyncreturn
    return self.decoderesponse(response)
  File "D:\Python37\lib\idlelib\rpc.py", line 271, in decoderesponse
    raise what
UnicodeEncodeError: 'UCS-2' codec can't encode characters in position 32-32: Non-BMP character not supported in Tk

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "D:\Python37\lib\idlelib\run.py", line 158, in main
    print_exception()
  File "D:\Python37\lib\idlelib\run.py", line 234, in print_exception
    print_exc(typ, val, tb)
  File "D:\Python37\lib\idlelib\run.py", line 220, in print_exc
    print_exc(type(context), context, context.__traceback__)
  File "D:\Python37\lib\idlelib\run.py", line 232, in print_exc
    print(line, end='', file=efile)
  File "D:\Python37\lib\idlelib\run.py", line 362, in write
    return self.shell.write(s, self.tags)
  File "D:\Python37\lib\idlelib\rpc.py", line 608, in __call__
    value = self.sockio.remotecall(self.oid, self.name, args, kwargs)
  File "D:\Python37\lib\idlelib\rpc.py", line 220, in remotecall
    return self.asyncreturn(seq)
  File "D:\Python37\lib\idlelib\rpc.py", line 251, in asyncreturn
    return self.decoderesponse(response)
  File "D:\Python37\lib\idlelib\rpc.py", line 271, in decoderesponse
    raise what
UnicodeEncodeError: 'UCS-2' codec can't encode characters in position 32-32: Non-BMP character not supported in Tk

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "D:\Python37\lib\idlelib\run.py", line 162, in main
    traceback.print_exception(type, value, tb, file=sys.__stderr__)
  File "D:\Python37\lib\traceback.py", line 105, in print_exception
    print(line, file=file, end="")
  File "D:\Python37\lib\idlelib\run.py", line 362, in write
    return self.shell.write(s, self.tags)
  File "D:\Python37\lib\idlelib\rpc.py", line 608, in __call__
    value = self.sockio.remotecall(self.oid, self.name, args, kwargs)
  File "D:\Python37\lib\idlelib\rpc.py", line 220, in remotecall
    return self.asyncreturn(seq)
  File "D:\Python37\lib\idlelib\rpc.py", line 251, in asyncreturn
    return self.decoderesponse(response)
  File "D:\Python37\lib\idlelib\rpc.py", line 271, in decoderesponse
    raise what
UnicodeEncodeError: 'UCS-2' codec can't encode characters in position 32-32: Non-BMP character not supported in Tk

=============================== RESTART: Shell ===============================

如您所见,shell 似乎进入了一个无限循环以尝试处理错误,然后重新启动 shell 以防止卡住。 有什么办法可以 a) 使str对错误处理程序的工作方式不同,或者 b) 防止 shell 重新启动以便正确显示错误?

从snakecharmerb 和两个问题中获取想法,我已经实现了一些代码来检查模块是否正在IDLE 中运行,如果是,则该函数是否正在被错误处理程序调用。 测试似乎工作正常。 我有以下检查空闲运行环境

IN_IDLE = False
for item in ['idlelib.__main__','idlelib.run','idlelib']:
    IN_IDLE = IN_IDLE or item in sys.modules

下面是新的__str__函数

    def __str__(self):
        """ Return str(self). """
        if IN_IDLE:
            # Check for caller. If string is being printed, modify
            # output to be IDLE-friendly (no non-BMP characters)
            callername = sys._getframe(1).f_code.co_name
            if callername == '_some_str':
                rstr = ''
                for char in self.__raw:
                    if ord(char) > 0xFFFF:
                        rstr += '\\U'+hex(ord(char))[2:].zfill(8)
                    else:
                        rstr += repr(char)[1:-1]
                return rstr
            else:
                return self.__raw
        else:
            return self.__raw

其中self.__raw保存对象的原始文本表示。 我缓存它是为了提高效率,因为对象是不可变的。

当然,虽然这确实解决了这个问题,但我觉得 python 不应该在发生这种情况时重新启动整个 shell。 将在 bugs.python.org 上发布

编辑:作为问题 36698发布在bugs.python.org 上

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM