【问题标题】:Python utf-coding problem with command line命令行的Python utf编码问题
【发布时间】:2011-08-21 11:45:58
【问题描述】:

在过去的几天里,我一直在学习 Python 编程,但我仍然只是一个初学者。最近,我为此目的使用了《云端代码》一书。问题是,虽然所有这些教科书都彻底涵盖了广泛的主题,但它们只是触及了除英语之外的其他语言的 UTF-8 编码问题。向您提出我的问题 - 如何使以下批次的代码以我的母语正确显示 utf-8 字符。

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

class ChatError(Exception):
""" Wyjątki obsługujące wszelkiego rodzaju błędy w czacie."""
def __init__(self, msg):
    self.message = msg


# START: ChatMessage
class ChatMessage(object):
"""Pojedyncza wiadomość wysłana przez użytkownika czatu"""
def __init__(self, user, text):
    self.sender = user
    self.msg = text
    self.time = datetime.datetime.now()
def __str__(self):
    return "Od: %s o godzinie %s: %s" % (self.sender.username,
                                   self.time,
                                   self.msg)

# END: ChatMessage

# START: ChatUser
class ChatUser(object):
"""Użytkownik biorący udział w czacie"""
def __init__(self, username):
    self.username = username
    self.rooms = {}

def subscribe(self, roomname):
    if roomname in ChatRoom.rooms:
        room = ChatRoom.rooms[roomname]
        self.rooms[roomname] = room
        room.addSubscriber(self)
    else:
        raise ChatError("Nie znaleziono pokoju %s" % roomname)

def sendMessage(self, roomname, text):
    if roomname in self.rooms:
        room = self.rooms[roomname]
        cm = ChatMessage(self, text)
        room.addMessage(cm)
    else:
        raise ChatError("Użytkownik %s nie jest zarejestrowany w pokoju %s" % 
                        (self.username, roomname))

def displayChat(self, roomname, out):
    if roomname in self.rooms:
        room = self.rooms[roomname]
        room.printMessages(out)
    else:
        raise ChatError("Użytkownik %s nie jest zarejestrowany w pokoju %s" % 
                        (self.username, roomname))
# END: ChatUser

# START: ChatRoom
class ChatRoom(object):
"""A chatroom"""

rooms = {}

def __init__(self, name):
    self.name = name
    self.users = []
    self.messages = []
    ChatRoom.rooms[name] = self

def addSubscriber(self, subscriber):
    self.users.append(subscriber)
    subscriber.sendMessage(self.name, 'Użytkownik %s dołączył do dyskusji.' %
                           subscriber.username)

def removeSubscriber(self, subscriber):
    if subscriber in self.users:
        subscriber.sendMessage(self.name, 
                               "Użytkownik %s opóścił pokój." % 
                               subscriber.username)
        self.users.remove(subscriber)

def addMessage(self, msg):
    self.messages.append(msg)

def printMessages(self, out):
    print >>out, "Lista wiadomości: %s" % self.name
    for i in self.messages:
        print >>out, i
# END: ChatRoom

# START: ChatMain
def main():
room = ChatRoom("Main") 
markcc = ChatUser("MarkCC")
markcc.subscribe("Main")
prag = ChatUser("Prag")
prag.subscribe("Main")

markcc.sendMessage("Main", "Hej! Jest tu kto?")
prag.sendMessage("Main", "Tak, ja tu jestem.")
markcc.displayChat("Main", sys.stdout)


if __name__ == "__main__":
main()
# END: ChatMain

它取自上述书籍,但我无法让它在 Windows 命令行中正确显示非英文字符(即使它支持它们)。如您所见,我在开头添加了编码语句(# -- coding: utf-8 -),这要归功于代码完全可以工作。我也尝试使用 u"string" 语法,但无济于事 - 它返回以下消息:

UnicodeEncodeError: 'ascii' codec can't encode character u'\u017c' in position 5
1: ordinal not in range(128)

如何使这些字符正确显示?是的,我经常使用 UTF 格式的字符串。非常感谢您的帮助。

【问题讨论】:

  • 编码语句用于文件中的字符用户,而不是打印。你需要在print username.decode('utf-8') 行做一些事情来告诉 Python 将字符串解码为 un​​icode,然后它会自动正确编码

标签: python windows command-line utf-8


【解决方案1】:

尝试以这种方式调用 Python 解释器:

#!/usr/bin/python -S

import sys
sys.setdefaultencoding("utf-8")
import site

这会将全局默认编码设置为 utf-8。通常的默认编码是 ASCII。这在将字符串写入某些输出时使用,例如使用 print 等内置函数。

【讨论】:

  • 我想我在这里遗漏了一些明显的东西,所以请原谅我的无知。当我使用您的代码时,我得到: Traceback(最近一次调用最后一次):文件“D:\kody\basechat.py”,第 4 行,在 sys.setdefaultencoding("utf-8") AttributeError: “模块”对象没有属性“setdefaultencoding”
  • 我想我在这里遗漏了一些明显的东西,所以请原谅我的无知。当我使用您的代码时,我得到: Traceback(最近一次调用最后一次):文件“D:\kody\basechat.py”,第 4 行,在 sys.setdefaultencoding("utf-8") AttributeError: 'module'对象没有属性 'setdefaultencoding' 我猜问题出在 Python 的路径上,尽管我无法让它正常工作。如果是这种情况,当我在我的 Windows 机器上将代码放在 D:\kody\basechat.py 并在 D:\Python 2.5.4 中安装 Python 时,正确的路径是什么?
  • 我记得,Python 在运行site 后从sys 中删除setdefaultencoding,所以如果你想在site 之外使用它,你必须在import sys 之后立即调用reload(sys)
  • @ssokolow 是的,我想通了,但不幸的是这个提示不起作用(或者我做错了什么)。基本上它和 # -- coding: utf-8 - line - 代码编译并显示输出相同,但输出中在应该有非英文字母的地方充满了随机字符。没有它们中的任何一个都会引发 ASCII 异常。
  • @Mathias 是的,您错过了使用 -S 选项调用 Python 的部分(不要导入站点模块)。然后调用 setdefaultencoding,然后显式导入站点。这样做的原因是site模块在使用一次后就去掉了setdefaultencoding方法(所以以后不能改)。
【解决方案2】:

目前这对我有用:

#!/usr/bin/env python
# -*-coding=utf-8 -*-

【讨论】:

    【解决方案3】:

    好吧,我对python一无所知,对windows命令行也知之甚少,但有点谷歌搜索和:

    我认为问题在于 windows cmd shell 不支持 utf-8。如果我没记错的话,这应该让您对错误有更多的了解:
    http://wiki.python.org/moin/PrintFails

    (从这个问题获得链接:'Unicode characters in Windows command line - how?)。

    看起来你可以强迫 python 认为它可以使用 PYTHONIOENCODING 打印 UTF8。

    这个问题是关于寻找支持 utf8 的 windows shell:
    Is there a Windows command shell that will display Unicode characters?

    可能会有所帮助。希望你能解决你的问题。

    【讨论】:

    • 我希望就是这样。它会让一切变得容易。问题是我可以在控制台中写 utf-8 字符没问题。它只是在 Python 中以正确的方式显示它们是行不通的。
    • @Mathias:我注意到putty 可以很好地处理 UTF-8。正确显示它们不是 Python 的工作。这就是你的终端程序的工作。
    【解决方案4】:

    Windows 终端有时使用非 UTF-8 编码 (python: unicode in Windows terminal, encoding used?)。因此,您可能想尝试以下方法:

    stdout_encoding = sys.stdout.encoding
    
    
    def printMessages(self, out):
        print >>out, ("Lista wiadomości: %s" % self.name).decode('utf-8').encode(stdout_encoding)
        for i in self.messages:
            print >>out, i.decode('utf-8').encode(stdout_encoding)
    

    这会将您的字节字符串转换为字符串(您的文件表明它们以 UTF-8 编码),然后为您的终端对其进行编码。

    您可以在StackOverflow 上找到有关编码和解码的一般问题的有用信息。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-18
      • 2010-12-11
      • 1970-01-01
      • 2017-03-02
      • 2011-10-29
      • 2017-04-24
      相关资源
      最近更新 更多