【问题标题】:How to find a non-ascii byte in my code?如何在我的代码中找到非 ascii 字节?
【发布时间】:2011-11-19 09:11:14
【问题描述】:

在制作我的 App Engine 应用时,我突然遇到了一个错误,该错误会显示每两个请求:

    run_wsgi_app(application)
  File "/home/ubuntu/Programs/google/google_appengine/google/appengine/ext/webapp/util.py", line 98, in run_wsgi_app
    run_bare_wsgi_app(add_wsgi_middleware(application))
  File "/home/ubuntu/Programs/google/google_appengine/google/appengine/ext/webapp/util.py", line 118, in run_bare_wsgi_app
    for data in result:
  File "/home/ubuntu/Programs/google/google_appengine/google/appengine/ext/appstats/recording.py", line 897, in appstats_wsgi_wrapper
    result = app(environ, appstats_start_response)
  File "/home/ubuntu/Programs/google/google_appengine/google/appengine/ext/webapp/_webapp25.py", line 717, in __call__
    handler.handle_exception(e, self.__debug)
  File "/home/ubuntu/Programs/google/google_appengine/google/appengine/ext/webapp/_webapp25.py", line 463, in handle_exception
    self.error(500)
  File "/home/ubuntu/Programs/google/google_appengine/google/appengine/ext/webapp/_webapp25.py", line 436, in error
    self.response.clear()
  File "/home/ubuntu/Programs/google/google_appengine/google/appengine/ext/webapp/_webapp25.py", line 288, in clear
    self.out.seek(0)
  File "/usr/lib/python2.7/StringIO.py", line 106, in seek
    self.buf += ''.join(self.buflist)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xd7 in position 208: ordinal not in range(128)

我真的不知道这可能在哪里,它只在我使用特定函数时发生,但不可能跟踪我拥有的所有字符串。 这个字节可能是' " [ ] 等字符,但仅限于另一种语言

我怎样才能找到这个字节以及可能的其他字节?

我在 ubuntu 11.04 中使用 python 2.7 运行 GAE

谢谢。

*更新*

这是我最终使用的代码: 从编解码器导入 BOM_UTF8 从操作系统导入列表目录,路径 p = "路径"

def loopPath(p, times=0):
    for fname in listdir(p):
        filePath = path.join(p, fname)
        if path.isdir(filePath):
            return loopPath(filePath, times+1)

        if fname.split('.', 1)[1] != 'py': continue

        f = open(filePath, 'r')
        ln = 0
        for line in f:
            #print line[:3] == BOM_UTF8
            if not ln and line[:3] == BOM_UTF8:
                line = line[4:]
            col = 0
            for c in list(line):
                if ord(c) > 128:
                    raise Exception('Found "'+line[c]+'" line %d column %d in %s' % (ln+1, col, filePath))
                col += 1
            ln += 1
        f.close()

loopPath(p)

【问题讨论】:

  • 您是否尝试过在缓冲区的位置208 处查看字节'\0xd7',正如错误明显指出的那样?
  • 该缓冲区是 StringIO 的一个内部变量,它在 GAE 的代码中非常深入。并且缓冲区不会告诉我它在我的代码中的确切位置,只有很多文本......

标签: python encoding ascii


【解决方案1】:

只需遍历每一行代码中的每个字符。类似的东西:

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

data = open(sys.argv[1])
line = 0
for l in data:
    line += 1
    char = 0
    for s in list(unicode(l,'utf-8')):
        char += 1
        try:
            s.encode('ascii')
        except:
            print 'Non ASCII character at line:%s char:%s' % (line,char)

【讨论】:

  • 可以使用 ord(s) > 128 来简化
【解决方案2】:

当我将 UTF-8 文件翻译成 latin1 LaTeX 时,我遇到了类似的问题。我想要一个文件中所有邪恶 Unicode 字符的列表。

这可能是你需要的更多,但我使用了这个:

UNICODE_ERRORS = {}

def fortex(exc):
    import unicodedata, exceptions
    global UNICODE_ERRORS
    if not isinstance(exc, exceptions.UnicodeEncodeError):
        raise TypeError("don't know how to handle %r" % exc)
    l = []
    print >>sys.stderr, "   UNICODE:", repr(exc.object[max(0,exc.start-20):exc.end+20])
    for c in exc.object[exc.start:exc.end]:
        uname = unicodedata.name(c, u"0x%x" % ord(c))
        l.append(uname)
        key = repr(c)
        if not UNICODE_ERRORS.has_key(key): UNICODE_ERRORS[key] = [ 1, uname ]
        else: UNICODE_ERRORS[key][0] += 1
    return (u"\\gpTastatur{%s}" % u", ".join(l), exc.end)

def main():    
    codecs.register_error("fortex", fortex)
    ...
    fileout = codecs.open(filepath, 'w', DEFAULT_CHARSET, 'fortex')
    ...
    print UNICODE_ERROS

有用吗?

以下是 Python 文档的匹配摘录:

codecs.register_error(name, error_handler) 在名称name下注册错误处理函数error_handler。 error_handler 将在编码和解码过程中调用,以防出错,当 name 指定为 errors 参数时。

对于编码,error_handler 将使用 UnicodeEncodeError 实例调用,其中包含有关错误位置的信息。错误处理程序必须引发此异常或其他异常,或者返回一个元组,其中替换输入的不可编码部分和应该继续编码的位置。编码器将对替换进行编码,并在指定位置继续对原始输入进行编码。负位置值将被视为相对于输入字符串的结尾。如果结果位置超出范围,则会引发 IndexError。

【讨论】:

  • +1 用于保存所有错误,但我不知道它是否保存了发现错误的位置
  • 如果你想跟踪它,请使用exc.start
【解决方案3】:

应该列出违规行:

grep -v [:alnum:] dodgy_file


$ cat test
/home/ubuntu/tmp/SO/c.awk

$ cat test2
/home/ubuntu/tmp/SO/c.awk
な

$ grep -v [:alnum:] test

$ grep -v [:alnum:] test2
な

【讨论】:

  • @shedokan - 想解释一下为什么? cmd-line 可以成为你最好的朋友!学会使用它真的很值得。学习一些标准的 linux 工具,如 grep、sed、awk、sort、uniq 并使用管道连接它们,为您提供了世界上任何 GUI 程序都无法比拟的工具集!
  • 我是一个 Windows 用户,以前不必在黑色文本上看到任何白色 :) 我只是将 linux 用于 GAE 而已。尽管它们可能很强大,但我不需要它们,所以学习它们没有意义,即使它们有时很有用
  • 但你确实需要,即使在 Windows 上!安装cygwin;它们非常很有用,所以请重新考虑你的技术启蒙之路。实用腰带中的更多工具意味着您能够更好地应对新挑战。只是我的 10c
【解决方案4】:

你可以使用命令:

grep --color='auto' -P -n "[\x80-\xFF]" file.xml

这将为您提供行号,并以红色突出显示非 ascii 字符。

复制自How do I grep for all non-ASCII characters in UNIX。 Fredrik 的回答很好,但并不完全正确,因为它还可以找到非字母数字的 ASCII 字符。

【讨论】:

    【解决方案5】:

    当文本被视为单行时,此 Python 脚本会在文本中给出违规字符及其索引:

    [(index, char) for (index, char) in enumerate(open('myfile').read()) if ord(char) > 127]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-05-13
      • 1970-01-01
      • 2017-01-15
      • 2014-09-16
      • 1970-01-01
      • 2010-10-15
      • 1970-01-01
      相关资源
      最近更新 更多