Python 3中使用Farsi/Arabic字符的print()函数

22
I simplified my code for better understanding. here is the problem :
case 1:
# -*- coding: utf-8 -*-

text = "چرا کار نمیکنی؟" # also using u"...." results the same
print(text)

输出:

UnicodeEncodeError: 'charmap' codec can't encode characters in position 0-2: character maps to <undefined>

案例2:
text = "چرا کار نمیکنی؟".encode("utf-8") 
print(text)

没有输出。

案例 3:

import sys

text = "چرا کار نمیکنی؟".encode("utf-8")
sys.stdout.buffer.write(text)

输出:

چرا کار نمیکنی؟

我知道第三种情况可以工作,但我想要使用其他函数,比如 print(),write(str())等等。

我还阅读了有关 Unicode 的 Python 3 文档 here

并且在 stackoverflow 上阅读了几十个问题和答案。

here 这里有一篇长文解释了 Python 2.X 中的问题和答案。

简单的问题是:

如何使用 Python print() 函数打印波斯语或阿拉伯语等非 ASCII 字符?

更新 1: 正如许多人建议的那样,这个问题涉及到终端,所以我测试了以下情况:

case 4:

text = "چرا کار نمیکنی؟" .encode("utf-8")# also using u"...." results the same
print(text)

终端:

python persian_encoding.py > test.txt

test.txt :

b'\xda\x86\xd8\xb1\xd8\xa7 \xda\xa9\xd8\xa7\xd8\xb1 \xd9\x86\xd9\x85\xdb\x8c\xda\xa9\xd9\x86\xdb\x8c\xd8\x9f'

非常重要的更新:

在解决这个问题一段时间后,我终于找到了另一个解决方案,使cmd.exe可以完成工作(无需像ConEmu或其他第三方软件):

首先需要进行一些解释:

我们的主要问题并不涉及Python。这是Windows命令提示符字符集的问题(有关完整说明,请查看Arman的答案)。 因此...如果您将Windows命令提示符的字符集从默认的ASCII更改为UTF-8,则命令提示符将能够与UTF-8字符(如波斯语或阿拉伯语)交互。这种解决方案不能保证字符的良好表示(因为它们将打印出类似小方块的字符),但如果您想要使用UTF-8字符进行Python文件I/O,则这是一个很好的解决方案。

步骤:

在从命令行启动Python之前,请输入:

chcp 65001

现在像往常一样运行你的Python代码。

python testcode.py

结果在情况1下:

?????? ??? ??????

它运行时没有出现错误。

截图:

enter image description here

如需了解如何将字符集设为65001,请查看this以获取更多信息。


4
你使用什么平台、编辑器/终端?这不是 Python 的问题,更可能是你的输出编码无法编码波斯语文本。 - Mazdak
它在我的电脑上运行正常:>>> text = "چرا کار نمیکنی؟" >>> print(text) چرا کار نمیکنی؟唯一的困难是在复制粘贴时字符阅读顺序的反转。 - Flint
@Kasramvd Python 3,Windows 10,IntelliJ 9 - Soorena
@Kasramvd 我已经搜索过了,无论使用哪个终端或IDE,结果都是一样的。如果你阅读BPL答案,你会发现无论你使用哪个终端或平台,print()函数或write()到文件函数都不起作用。 - Soorena
问题无处不在,波斯文件名,波斯文本文件,为波斯字符写入文件,任何事情。 - Soorena
显示剩余4条评论
4个回答

15

您的代码是正确的,因为它在我的电脑上使用Python 2和3都可以工作(我在OS X上):

~$ python -c 'print "تست"'
تست
~$ python3 -c 'print("تست")'
تست

问题在于您的终端无法输出 Unicode 字符。您可以通过将输出重定向到文件,如 python3 my_file.py > test.txt,并使用编辑器打开该文件来验证它。

如果您使用的是 Windows 系统,您可以使用像 Console2ConEmu 这样的终端,它们比 Windows 命令提示符更好地渲染 Unicode。

这些终端也可能会因为 Windows 的错误代码页/编码而出现错误。有一个小的 Python 包可以修复它们(将它们正确配置):

1- 安装 此包pip install win-unicode-console

2- 将以下代码放在您的 Python 文件的顶部:

try:
    # Fix UTF8 output issues on Windows console.
    # Does nothing if package is not installed
    from win_unicode_console import enable
    enable()
except ImportError:
    pass
如果在重定向到文件时遇到错误,您可以通过设置io编码来解决它:
在Windows命令行中:
SET PYTHONIOENCODING=utf-8

在 Linux/OS X 终端中:

export PYTHONIOENCODING=utf-8

一些要点

  • 在Python 3中,不需要使用u"aaa"语法。字符串字面值默认为Unicode。
  • 在Python 3中,文件的默认编码是UTF8,因此不需要编码声明注释(例如# -*- coding: utf-8 -*-)。

我更新了我的问题,请查看。 - Soorena
@Arman Ordookhani:仅供记录,win-unicode-console在conemu(case1)上对我有效,但在命令提示符上无效。在py2.x上安装也遇到了问题。 - BPL
@arman-ordookhani 工作得非常好!!!! - Soorena
@BPL 我认为命令提示符无法显示波斯字符(只支持非常小的Unicode子集),或者可能有一些cmd.exe的配置我不知道。 - Arman Ordookhani
尝试将它写入文件时无法工作。 - Jawad

6

输出结果基本上取决于您在哪个平台和终端上运行代码。我们来看看下面的片段在不同的Windows终端上运行2.x或3.x时的情况:

# -*- coding: utf-8 -*-
import sys

def case1(text):
    print(text)

def case2(text):
    print(text.encode("utf-8"))

def case3(text):
    sys.stdout.buffer.write(text.encode("utf-8"))

if __name__ == "__main__":
    text = "چرا کار نمیکنی؟"

    for case in [case1, case2, case3]:
        try:
            print("Running {0}".format(case.__name__))
            case(text)
        except Exception as e:
            print(e)

        print('-'*80)

Results

Python 2.x

Sublime Text 3 3122

    Running case1
    'charmap' codec can't encode characters in position 0-2: character maps to <undefined>
    --------------------------------------------------------------------------------
    Running case2
    b'\xda\x86\xd8\xb1\xd8\xa7 \xda\xa9\xd8\xa7\xd8\xb1 \xd9\x86\xd9\x85\xdb\x8c\xda\xa9\xd9\x86\xdb\x8c\xd8\x9f'
    --------------------------------------------------------------------------------
    Running case3
    چرا کار نمیکنی؟--------------------------------------------------------------------------------

ConEmu v151205

    Running case1
    ┌åÏ▒Ϻ ┌®ÏºÏ▒ ┘å┘à█î┌®┘å█îσ
    --------------------------------------------------------------------------------
    Running case2
    'ascii' codec can't decode byte 0xda in position 0: ordinal not in range(128)
    --------------------------------------------------------------------------------
    Running case3
    'file' object has no attribute 'buffer'
    --------------------------------------------------------------------------------

Windows命令提示符

    Running case1
    ┌åÏ▒Ϻ ┌®ÏºÏ▒ ┘å┘à█î┌®┘å█îσ
    --------------------------------------------------------------------------------

    Running case2
    'ascii' codec can't decode byte 0xda in position 0: ordinal not in range(128)
    --------------------------------------------------------------------------------

    Running case3
    'file' object has no attribute 'buffer'
    --------------------------------------------------------------------------------

Python 3.x

Sublime Text 3 3122

    Running case1
    'charmap' codec can't encode characters in position 0-2: character maps to <undefined>
    --------------------------------------------------------------------------------
    Running case2
    b'\xda\x86\xd8\xb1\xd8\xa7 \xda\xa9\xd8\xa7\xd8\xb1 \xd9\x86\xd9\x85\xdb\x8c\xda\xa9\xd9\x86\xdb\x8c\xd8\x9f'
    --------------------------------------------------------------------------------
    Running case3
    چرا کار نمیکنی؟--------------------------------------------------------------------------------

ConEmu v151205

    Running case1
    'charmap' codec can't encode characters in position 0-2: character maps to <undefined>
    --------------------------------------------------------------------------------
    Running case2
    b'\xda\x86\xd8\xb1\xd8\xa7 \xda\xa9\xd8\xa7\xd8\xb1 \xd9\x86\xd9\x85\xdb\x8c\xda\xa9\xd9\x86\xdb\x8c\xd8\x9f'
    --------------------------------------------------------------------------------
    Running case3
    ┌åÏ▒Ϻ ┌®ÏºÏ▒ ┘å┘à█î┌®┘å█îσ--------------------------------------------------------------------------------

Windows 命令提示符

    Running case1
    'charmap' codec can't encode characters in position 0-2: character maps to <unde
    fined>
    --------------------------------------------------------------------------------

    Running case2
    b'\xda\x86\xd8\xb1\xd8\xa7 \xda\xa9\xd8\xa7\xd8\xb1 \xd9\x86\xd9\x85\xdb\x8c\xda
    \xa9\xd9\x86\xdb\x8c\xd8\x9f'
    --------------------------------------------------------------------------------

    Running case3
    ┌åÏ▒Ϻ ┌®ÏºÏ▒ ┘å┘à█î┌®┘å█îσ----------------------------------------------------
    ----------------------------

正如您所看到的,仅使用Sublime Text3终端(case3)就可以正常工作。其他终端不支持波斯语。这里的主要问题是,这取决于您使用哪个终端和平台。

解决方案(针对ConEmu)

像ConEmu这样的现代终端可以让您使用UTF8编码,如此处所述,因此,让我们尝试一下:

chcp 65001 & cmd

接下来再次运行脚本,针对2.x和3.x版本:

Python2.x

Running case1
��را کار نمیکنی؟[Errno 0] Error
--------------------------------------------------------------------------------
Running case2
'ascii' codec can't decode byte 0xda in position 0: ordinal not in range(128)
--------------------------------------------------------------------------------
Running case3
'file' object has no attribute 'buffer'
--------------------------------------------------------------------------------

Python3.x

Running case1
چرا کار نمیکنی؟
--------------------------------------------------------------------------------
Running case2
b'\xda\x86\xd8\xb1\xd8\xa7 \xda\xa9\xd8\xa7\xd8\xb1 \xd9\x86\xd9\x85\xdb\x8c\xda\xa9\xd9\x86\xdb\x8c\xd8\x9f'
--------------------------------------------------------------------------------
Running case3
چرا کار نمیکنی؟--------------------------------------------------------------------------------

如您所见,现在使用Python3的情况下,输出已经成功了(print)。所以...寓言的寓意是...更多地了解您的工具以及如何为您的用例正确配置它们;-)


我在问题中写道:我知道第三种情况可以工作,但我想使用其他函数,比如print(),write(str())等等。例如,考虑我想将这些字符写入文本文件,但它的输出仍然是字节字符,无论使用哪个文本编辑器打开该文件。 - Soorena
关于这个问题,你的回答并没有帮助到我。但是我非常感谢你为我的问题所付出的努力和时间。 - Soorena
1
@Soorena,我不知道为什么它对你没有帮助,我只是想让你明白输出取决于你使用的终端。如果你使用的是基于Qt编写的多平台GUI应用程序,关于文件打印等问题就不会有问题了。我很快会编辑我的问题。你使用的是哪个平台/终端/编辑器? - BPL
1
@Soorena 我又编辑了一下我的问题,希望有所帮助。我已经给出了conemu的解决方案。我使用了cygwin、msysgit和vs_cmd提示符,但我都不喜欢... conemu是一个很好的选择,让我想起了强大的Unix终端(虽然不如Unix终端那么强大),我向你推荐它 ;) - BPL
谢谢,我使用的是Console2而不是ConEmu,它们都很好用。 - Soorena
显示剩余3条评论

1
我无法重现这个问题。这是我的脚本 p.py
text = "چرا کار نمیکنی؟"
print(text)

并且执行 python3 p.py 的结果为:

چرا کار نمیکنی؟

你确定你正在使用Python 3吗?使用 python2 p.py 是针对Python 2的:

SyntaxError: Non-ASCII character '\xda' in file p.py on line 1, but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details

抱歉,这对我来说不是事实。 - Soorena

0

如果你执行 text.encode("utf-8") 这一部分,它将显示为 b'\xda\x86\xd8\xb1\xd8\xa7 \xda\xa9\xd8\xa7\xd8\xb1 \xd9\x86\xd9\x85\xdb\x8c\xda\xa9\xd9\x86\xdb\x8c\xd8\x9f'(在我的机器上)。

编辑 很抱歉修改了内容,但是我不能评论(因为声望不够)

即使在Python 2.7上,print(text)也能正常工作。在这里查看这个链接,这是我刚生成的。


同意。这里的文本被解释为字节。 - Soorena

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