【问题标题】:How to ensure all string literals are unicode in python如何确保所有字符串文字在python中都是unicode
【发布时间】:2023-03-28 11:06:01
【问题描述】:

我有一个相当大的 Python 代码库要处理。它有一个问题,一些字符串文字是字符串,而另一些是 unicode。这会导致错误。我正在尝试将所有内容都转换为 unicode。我想知道是否有可以将所有文字转换为 unicode 的工具。 IE。如果它发现这样的东西:

print "result code %d" % result['code']

到:

print u"result code %d" % result[u'code']

如果它对我使用 PyCharm 有帮助(如果有一个扩展可以做到这一点),但是我也很乐意使用类似的命令。希望有这样的工具。

【问题讨论】:

  • 为什么不用u"result code %d"
  • 你总是可以使用 Python 3 :)
  • @unutbu 你是完全正确的。我编辑了问题以包含它。傻我。
  • from future import unicode_literals?但问题完全有可能不是字符串文字,而是其他字节字符串来源(例如“错误”的 API 选择,或缺少 encode/decode 调用)。
  • @MattDMo 遗憾的是,我们正在使用一些仅支持 Python 2 的 3rd 方库

标签: python unicode unicode-literals


【解决方案1】:

您可以使用tokenize.generate_tokens 将 Python 代码的字符串表示分解为标记。 tokenize 还为您分类令牌。因此,您可以在 Python 代码中识别字符串文字。

然后不难操作令牌,在需要的地方添加'u'


import tokenize
import token
import io
import collections

class Token(collections.namedtuple('Token', 'num val start end line')):
    @property
    def name(self):
        return token.tok_name[self.num]

def change_str_to_unicode(text):    
    result = text.splitlines()
    # Insert a dummy line into result so indexing result
    # matches tokenize's 1-based indexing
    result.insert(0, '')
    changes = []
    for tok in tokenize.generate_tokens(io.BytesIO(text).readline):
        tok = Token(*tok)
        if tok.name == 'STRING' and not tok.val.startswith('u'):
            changes.append(tok.start)

    for linenum, s in reversed(changes):
        line = result[linenum]
        result[linenum] = line[:s] + 'u' + line[s:]
    return '\n'.join(result[1:])

text = '''print "result code %d" % result['code']
# doesn't touch 'strings' in comments
'handles multilines' + \
'okay'
u'Unicode is not touched'
'''

print(change_str_to_unicode(text))

产量

print u"result code %d" % result[u'code']
# doesn't touch 'strings' in comments
u'handles multilines' + u'okay'
u'Unicode is not touched'

【讨论】:

  • 效果很好。非常感谢您将这个答案放在一起。
  • 你太棒了,先生。
【解决方案2】:

试试这个(使用正则表达式),它比@unutbu 的解决方案短。
但是有一个循环孔,包含# 的字符串不能用这个。

import re
scode = '''
print "'Hello World'" # prints 'Hello World'
u'Unicode is unchanged'"""
# so are "comments"'''
x1 = re.compile('''(?P<unicode>u?)(?P<c>'|")(?P<data>.*?)(?P=c)''')

def repl(m):
    return "u%(c)s%(data)s%(c)s" % m.groupdict()

fcode = '\n'.join(
      [re.sub(x1,repl,i)
       if not '#' in i
       else re.sub(x1,repl,i[:i.find('#')])+i[i.find('#'):]
       for i in scode.splitlines()])
print fcode

输出:

print u"'Hello World'" # prints 'Hello World'
u'Unicode is unchanged'
# so are "comments"

对于#,我有这个(而且它比@unutbu 的解决方案长:|)

import re
scode = '''print "'Hello World'"  # prints 'Hello World'
u'Unicode is unchanged'
# so are "comments"
'#### Hi' # 'Hi' '''

x1 = re.compile('''(?P<unicode>u?)(?P<c>'|")(?P<data>.*?)(?P=c)''')

def in_string(text,index):
    curr,in_l,in_str,level = '',0,False,[]

    for c in text[:index+1]:
        if c == '"' or c == "'":
            if in_str and curr == c:
                instr = False
                curr = ''
                in_l -= 1
            else:
                instr = True
                curr = c
                in_l += 1
        level.append(in_l)
    return bool(level[index])

def repl(m):
    return "u%(c)s%(data)s%(c)s" % m.groupdict()

def handle_hashes(i):
    if i.count('#') == 1:
        n = i.find('#')
    else:
        n = get_hash_out_of_string(i)
    return re.sub(x1,repl,i[:n]) + i[n:]

def get_hash_out_of_string(i):
    n = i.find('#')
    curr = i[:]
    last = (len(i)-1)-''.join(list(reversed(i))).find('#')
    while in_string(curr,n) and n < last:
        curr = curr[:n]+' '+curr[n+1:]
        n = curr.find('#')
    return n

fcode = '\n'.join(
    [re.sub(x1,repl,i)
     if not '#' in i
     else handle_hashes(i)
     for i in scode.splitlines()])

print fcode

输出:

print u"'Hello World'"  # prints 'Hello World'
u'Unicode is unchanged'
# so are "comments"
u'#### Hi' # 'Hi' 

【讨论】:

  • 我不鼓励使用正则表达式来解析/操作像 Python 这样的不规则语言,特别是因为该语言的标准库中包含一个非常好的 Python 解析器。因此-1。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-04-14
  • 2020-03-28
  • 2014-01-01
  • 2014-04-23
  • 2014-01-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多