<p>首先,下面是一个在Windows上重现错误的最小示例:</p>
<pre><code>import subprocess
with subprocess.Popen("cmd /c echo ü", stdout=subprocess.PIPE, text=True) as Process:
for Line in Process.stdout:
print(Line)
</code></pre>
<p>据我所知,问题是这样的(我整理了一些我发现的信息和例子,但并不确定每件事都是正确的。我欢迎更正。)</p>
<ul>
<li><code>ü</code>字符是Unicode中的代码点252=0xfc,<a href="https://unicode-table.com/en/00FC/" rel="nofollow noreferrer">https://unicode-table.com/en/00FC/</a>)。</li>
<li>Python correct将<code>ü</code>字符传递到控制台,您可以使用此示例进行测试(请确保将文件保存为UTF-8):</li>
</ul>
<pre><code>import subprocess
print(ord('ü'))
subprocess.call("cmd /c echo ü")
</code></pre>
<p>我不知道为什么一开始就这样。(这个答案可能是原因:<a href="https://stackoverflow.com/a/32176732/880783">https://stackoverflow.com/a/32176732/880783</a>)</p>
<ul>
<li>控制台在内部使用的不是Unicode。例如,在<a href="http://www.asciitable.com/" rel="nofollow noreferrer">ASCII table</a>中,<code>ü</code>字符位于位置129=0x81(听起来很熟悉?)。</li>
<li>所以当控制台返回那个字符时,Python认为它是Unicode代码点,但是<a href="https://unicodelookup.com/#0x81" rel="nofollow noreferrer">0x81 is not defined</a>。因此产生了错误。</li>
</ul>
<p>关键是让Python了解如何对它从流程中获得的内容进行编码。在我的示例(Windows控制台)中,我尝试了以下几种编码(请参见<a href="https://docs.python.org/3/library/codecs.html" rel="nofollow noreferrer">list here</a>):</p>
<pre><code>import subprocess
Encoding = 'cp850'
with subprocess.Popen("cmd /c echo ü", stdout=subprocess.PIPE, text=True, encoding=Encoding) as Process:
for Line in Process.stdout:
print(Line)
</code></pre>
<ul>
<li><code>'ascii'</code>失败,出现<code>ordinal not in range(128)</code>错误(可能不包括扩展的ASCII)。</li>
<li><code>'cp1252'</code>失败,出现<code>character maps to <undefined></code></li>
<li><code>'latin_1'</code>可以工作,但在VS代码中的调试控制台上输出一个方框字符(``)。</li>
<li><code>'cp850'</code>似乎可以工作,输出一个<code>ü</code>字符。</li>
</ul>
<p>所以我现在就坚持<code>'cp850'</code>,看看进展如何。</p>