尝试打印ASCII字符128到160,为什么只打印到157就停止了?

4

我是Python新手,正在学习编码、Unicode编码、ASCII编码等。我想按照它们的代码值使用chr()函数打印ASCII字符。

def table_ascii():
    "procédure imprimant une table des caractères ascii avec leur valeurs"
    i = 127
    while i < 258:
        print(f"{i} -> {chr(i)}")
        i += 1

table_ascii()

很遗憾,结果是错误的。它停留在代码157处:

127 ->  
128 ->  
129 ->  
130 ->  
131 ->  
132 ->  

133 ->  

134 ->  
135 ->  
136 ->  
137 ->      
138 ->  
139 ->  
140 ->  
142 ->  
143 ->  
144 ->  
146 ->  
147 ->  
148 ->  
149 ->  
150 ->  
151 ->  
152 ->  
154 ->  
        155 ->  

157 ->

我知道这些代码不返回任何内容,但为什么它们会停止进程呢?

设置:

  • Python 3.8.10 (默认值,Sep 28 2021, 16:10:42) [GCC 9.3.0] 在 Linux 上
  • 使用 VIM - Vi IMproved 8.1

当我在 Visual Studio Code 中运行这段代码时,脚本通过 256 输出结果。但在我的控制台(Linux Mate)中,它阻塞了。这对我来说很难理解...


12
你的任务前提存在缺陷。ASCII只定义了整数值为0-127的字符。_没有ASCII字符对应于整数128-160_。将128-160解释为字符严格要求使用 ASCII 以外的编码(但可能是ASCII的超集)。 - Brian61354270
3
chr 返回 Unicode 字符串,由于历史原因,代码点 127 到 159 没有定义(可打印)字符。 - chepner
1
@Brian https://zh.wikipedia.org/wiki/Extended_ASCII - Abhijit Sarkar
2
另外一点,由于你正在学习,可以使用循环范围来代替手动递增i,例如for i in range(0, 128) - Abhijit Sarkar
2
我确认在我的机器上(Ubuntu 20.4,Python 3.9)有相同的效果:在ipython中运行代码或作为脚本在终端中显示,它会停在157。 - nonDucor
显示剩余12条评论
3个回答

7
首先,ASCII 只能表示到 127(0x7F)。chr() 返回的实际上是 Unicode 字符。
我认为问题在于,当 U+9D(157)操作系统命令(OSC) 被打印时,你的终端会开始一个控制字符串并等待字符串终止符,例如 U+9C 字符串终止符、U+1B 转义字符 后跟 U+5C 反斜杠或 U+7 BEL。由于后面没有任何这些序列被打印出来,终端停止显示输出。有关更多信息,请参见维基百科上的ANSI 转义码 § Fe 转义序列C1 控制码
Unicode 字符 U+80(128)到 U+9F(159)是控制字符,意味着它们通常不可打印,因此你一开始就不可能得到有意义的输出。

4
太好了!我将打印行更改为 print(f"{i} -> {chr(i)}{chr(0x9c)}"),以确保它始终被终止,这样它就起作用了。 - nonDucor

4

如评论中提到的那样,介于128和160之间的字符有点像无主之地。 它们在Unicode规范中没有定义,但它们可能对各种显示器具有特殊意义。 这就是为什么Unicode不会涉及它们的原因 - 太多的变量使用存在。

像Linux xterm这样的终端接受控制代码来执行诸如以颜色显示文本之类的操作。 查看Xterm控制序列,我们可以看到

Privacy Message (PM is 0x9e)

这是158的十进制数,是xterm 8位控制字符之一。它开启了一个“私人信息”,直到出现一个定义好的字符串终止符。 xterm没有实现“私人信息”,从您的输出来看,它只是忽略剩余的输出作为该消息的一部分。

这是VT100类型的东西。一些终端可能会实现某些操作。其他终端可能将该八位组映射到某个字符。您不会找到任何一致的实现。


1

来自https://www.wikiwand.com/en/C0_and_C1_control_codes#/Unicode

在Unicode中

Unicode为了与ISO/IEC 2022兼容,在一般类别Cc(控制)中保留了65个代码点。这些是:

  1. U+0000 – U+001F(C0控制字符)和U+007F(删除),分配给基本拉丁字母块
  2. U+0080 – U+009F(C1控制字符),分配给拉丁-1补充块。

Unicode仅为以下代码指定语义:

  1. U+0009 – U+000D,U+001C – U+001F
  2. U+0085(NEL,下一行。相当于CR + LF。用于标记某些IBM大型机的行尾。)

其余的控制字符对于Unicode来说是透明的
它们的含义留给更高级别的协议。

在通用类别 Cf(格式)中,还有其他格式效应器字符,例如:
  1. 零宽连接器
  2. 非连接器(控制连字)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接