【问题标题】:Python: print unicode string stored as a variable [closed]Python:打印存储为变量的unicode字符串[关闭]
【发布时间】:2016-09-18 00:49:26
【问题描述】:

在 Python (3.5.0) 中,我想将包含 unicode 符号的字符串(更准确地说,是从维基词典以 JSON 格式检索的 IPA 符号)打印到屏幕或文件中,例如

print("\u02c8w\u0254\u02d0t\u0259\u02ccm\u025bl\u0259n")

正确打印

ˈwɔːtəˌmɛlən

- 但是,每当我在变量中使用字符串时,例如

ipa = '\u02c8w\u0254\u02d0t\u0259\u02ccm\u025bl\u0259n'
print(ipa)

它只是按原样打印出字符串,即

\u02c8w\u0254\u02d0t\u0259\u02ccm\u025bl\u0259n

这没什么帮助。

我已经尝试了几种方法来避免这种情况(比如通过deocde/encode),但都没有帮助。

我不能合作

u'\u02c8w\u0254\u02d0t\u0259\u02ccm\u025bl\u0259n'

因为我已经将字符串作为变量检索(作为正则表达式匹配的结果)并且在我的代码中没有任何地方输入实际文字。

也有可能是我在从JSON结果转换的过程中出错了;到目前为止,我已经使用str(f.read()) 将字节流转换为字符串,通过正则表达式提取了 IPA 部分(并对双反斜杠进行了替换)并将其存储在字符串变量中。

编辑:
这是我到目前为止的代码:

def getIPAen(word):
    url = "https://en.wiktionary.org/w/api.php?action=query&titles=" + word + "&prop=revisions&rvprop=content&format=json"
    jsoncont = str((urllib.request.urlopen(url)).read())
    jsonmatch = re.search("\{IPA\|/(.*?)/\|", jsoncont).group(1)
    #print("jsomatch: " + jsonmatch)
    ipa = jsonmatch.replace("\\\\", "\\")
    #print("ipa: " + ipa)
    print(ipa)

json.loads修改后:

def getIPAen(word):
    url = "https://en.wiktionary.org/w/api.php?action=query&titles=" + word + "&prop=revisions&rvprop=content&format=json"
    jsoncont = str((urllib.request.urlopen(url)).read())
    jsonmatch = re.search("\{IPA\|/(.*?)/\|", jsoncont).group(1)
    #print("jsonmatch: " + jsonmatch)
    jsonstr = "\"" + jsonmatch + "\""
    #print("jsonstr: " + jsonstr)
    jsonloads = json.loads(jsonstr)
    #print("jsonloads: " + jsonloads)
    print(jsonloads)

对于这两个版本,当调用它时

getIPAen("watermelon")

我得到的是:

\u02c8w\u0254\u02d0t\u0259\u02ccm\u025bl\u0259n

有没有办法让字符串打印/写入已经解码,即使作为变量传递?

【问题讨论】:

  • 请创建一个简短的完整程序来演示该问题。请将程序及其输出复制粘贴到您的问题中。有关详细信息,请参阅 minimal reproducible example 和更一般的 How to Ask
  • Here 是一个示例程序,可以产生您想要的输出。
  • @Robᵩ 我将完整代码添加到我的帖子中。这样可以吗? - 我认为它会变得太长了。很抱歉给您带来不便,这是我第一次在这里发帖。对于您的示例程序:谢谢,它有效-实际上我的示例也有效,目前无法重建为什么我认为它没有或在以这种方式解释之前我到底有什么。

标签: python json string unicode


【解决方案1】:

你没有这个值:

ipa = '\u02c8w\u0254\u02d0t\u0259\u02ccm\u025bl\u0259n'

因为 值打印得很好:

>>> ipa = '\u02c8w\u0254\u02d0t\u0259\u02ccm\u025bl\u0259n'
>>> print(ipa)
ˈwɔːtəˌmɛlən

至少有文字\u字符:

ipa = '\\u02c8w\\u0254\\u02d0t\\u0259\\u02ccm\\u025bl\\u0259n'

那些\\ 序列每个都是一个 反斜杠,但是被转义了。由于这是 JSON,字符串可能也被双引号括起来:

ipa = '"\\u02c8w\\u0254\\u02d0t\\u0259\\u02ccm\\u025bl\\u0259n"'

因为该字符串有文字反斜杠,这正是正在打印的内容:

>>> ipa = '"\\u02c8w\\u0254\\u02d0t\\u0259\\u02ccm\\u025bl\\u0259n"'
>>> print(ipa)
"\u02c8w\u0254\u02d0t\u0259\u02ccm\u025bl\u0259n"
>>> ipa[1]
'\\'
>>> print(ipa[1])
\
>>> ipa[2]
'u'

注意 echoed 值如何显示字符串文字,您可以将其复制并粘贴回 Python,因此 \ 字符会再次为您转义。

该值是有效的 JSON,使用\uhhhh 转义序列。将其解码为 JSON:

import json

print(json.loads(ipa))

现在你有了一个合适的 Python 值:

>>> import json
>>> json.loads(ipa)
'ˈwɔːtəˌmɛlən'
>>> print(json.loads(ipa))
ˈwɔːtəˌmɛlən

请注意,在 Python 3 中,几乎所有代码点都会直接打印,即使repl() 为您创建了文字。 json.loads() 结果直接显示值中的所有文本,即使大多数是非 ASCII。

此值不包含文字反斜杠或u 字符:

>>> result = json.loads(ipa)
>>> result[0]
'ˈ'
>>> result[1]
'w'

附带说明,在调试此类问题时,您确实希望使用 repr()ascii() 函数,以便获得可让您正确重现字符串值的表示:

>>> print(repr(ipa))
'"\\u02c8w\\u0254\\u02d0t\\u0259\\u02ccm\\u025bl\\u0259n"'
>>> print(ascii(ipa))
'"\\u02c8w\\u0254\\u02d0t\\u0259\\u02ccm\\u025bl\\u0259n"'
>>> print(repr(result))
'ˈwɔːtəˌmɛlən'
>>> print(ascii(result))
'\u02c8w\u0254\u02d0t\u0259\u02ccm\u025bl\u0259n'

请注意,只有在具有实际 Unicode 代码点超出 Latin-1 范围的字符串上的 ascii() 会产生实际的 \uhhhh 转义序列。 (对于repl() 输出,如果您的终端或控制台无法处理特定字符,Python 仍然可以退回到\uhhhh 转义)。

至于您的更新,只需将 整个响应 解析为 JSON,然后从中加载正确的数据。您的代码将 bytes 响应正文转换为 repr()str() 字节调用确实解码数据;相反,您 双重转义以这种方式)。将来自网络的字节解码为 UTF-8,然后将该数据提供给 json.loads()

import json
import re
import urllib.request
from urllib.parse import quote_plus


baseurl = "https://en.wiktionary.org/w/api.php?action=query&titles={}&prop=revisions&rvprop=content&format=json"

def getIPAen(word):
    url = baseurl.format(quote_plus(word))
    jsondata = urllib.request.urlopen(url).read().decode('utf8')
    data = json.loads(jsondata)
    for page in data['query']['pages'].values():
        for revision in page['revisions']:
            if 'IPA' in revision['*']:
                ipa = re.search(r"{IPA\|/(.*?)/\|", revision['*']).group(1)
                print(ipa)

请注意,我还确保将word引用到 URL 查询字符串中。

上面打印出它找到的任何 IPA:

>>> getIPAen('watermelon')
ˈwɔːtəˌmɛlən
>>> getIPAen('chocolate')
ˈtʃɒk(ə)lɪt

【讨论】:

  • 对于第一个问题(做ipa = \u...),我无法弄清楚为什么我认为它不起作用或实际问题是什么,然后才这样说,但正如你所说,这完全正常。对不起,不知道为什么我没有写。
  • 关于反斜杠的第二个问题:我从 JSON 中提取的字符串没有双引号,但确实有双反斜杠,然后,正如我所写,我将其替换为单个反斜杠 (.replace("\\\\", "\\") - 如果我离开这个,它会打印双反斜杠。因此,我要打印的字符串确实看起来像我发布的示例,即\\u02c8w\\u0254\\u02d0t\\u0259\\u02ccm\\u025bl\\u0259n,然后打印带有单个反斜杠的版本。
  • 您的 json.loads(ipa) 提示有效 - 在手动添加双引号后 - 当我像这样尝试但不在我的函数中时,我现在不明白为什么。我会在一分钟内将我的实际代码添加到我的原始帖子中。
  • 感谢repr()ascii() 的提示,我不知道。
  • @lemontree:那里,更新了。您通过导致双重编码来破坏 JSON。不要在字节对象上调用 str()。只需解码 JSON 并使用给定的数据
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-08-14
  • 2014-09-16
  • 1970-01-01
  • 2014-08-23
  • 2023-03-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多