phk*_*phk 8 python debugging unicode monkeypatching python-2.7
我有一个大型项目,在各个地方有问题的隐式Unicode转换(coersions)以例如:
someDynamicStr = "bar" # could come from various sources
# works
u"foo" + someDynamicStr
u"foo{}".format(someDynamicStr)
someDynamicStr = "\xff" # uh-oh
# raises UnicodeDecodeError
u"foo" + someDynamicStr
u"foo{}".format(someDynamicStr)
Run Code Online (Sandbox Code Playgroud)
(也可能是其他形式.)
现在我想跟踪这些用法,特别是那些积极使用的代码.
如果我可以轻松地unicode用一个包装器替换构造函数会很好,它会检查输入是否为type str并且encoding/ errorsparameters设置为默认值然后通知我(打印回溯等).
/编辑:
虽然没有直接关系的东西我找我碰到了如何使解码异常干脆离开这个光荣可怕的黑客(解码一个唯一的,即str到unicode,而不是周围的其他方法,请参阅https://开头的邮件. python.org/pipermail/python-list/2012-July/627506.html).
我不打算使用它,但对于那些与无效的Unicode输入和寻找快速修复(但请考虑副作用)的问题进行斗争可能会很有趣:
import codecs
codecs.register_error("strict", codecs.ignore_errors)
codecs.register_error("strict", lambda x: (u"", x.end)) # alternatively
Run Code Online (Sandbox Code Playgroud)
(互联网搜索codecs.register_error("strict"显示它显然用于某些真实项目.)
/编辑#2:
对于显式转换,我在monkeypatching的SO帖子的帮助下制作了一个片段:
class PatchedUnicode(unicode):
def __init__(self, obj=None, encoding=None, *args, **kwargs):
if encoding in (None, "ascii", "646", "us-ascii"):
print("Problematic unicode() usage detected!")
super(PatchedUnicode, self).__init__(obj, encoding, *args, **kwargs)
import __builtin__
__builtin__.unicode = PatchedUnicode
Run Code Online (Sandbox Code Playgroud)
这只会unicode()直接影响使用构造函数的显式转换,因此它不是我需要的.
/编辑#3:
线程" python内置类型的扩展方法! "让我觉得它实际上可能不容易实现(至少在CPython中).
/编辑#4:
很高兴在这里看到许多好的答案,太糟糕了我只能给出一次赏金.
与此同时,我遇到了一个类似的问题,至少在这个人试图实现的意义上:我可以关闭隐式Python unicode转换来查找我的混合字符串错误吗? 请注意,在我的情况下,抛出异常并不合适.在这里,我一直在寻找可能指向有问题代码的不同位置的东西(例如通过打印smth.)但不是可能退出程序或改变其行为的东西(因为这样我可以优先考虑修复的内容).
在另一方面,在Mypy项目(包括吉多·范罗苏姆)工作的人也可能会拿出类似的有益未来的某事,看在讨论https://github.com/python/mypy/issues/1141和最近https://github.com/python/typing/issues/208.
/编辑#5
我也遇到了以下情况,但还没来得及测试它:https://pypi.python.org/pypi/unicode-nazi
您可以注册一个自定义编码,每当使用它时都会打印一条消息:
\n\n代码在ourencoding.py:
import sys\nimport codecs\nimport traceback\n\n# Define a function to print out a stack frame and a message:\n\ndef printWarning(s):\n sys.stderr.write(s)\n sys.stderr.write("\\n")\n l = traceback.extract_stack()\n # cut off the frames pointing to printWarning and our_encode\n l = traceback.format_list(l[:-2])\n sys.stderr.write("".join(l))\n\n# Define our encoding:\n\noriginalencoding = sys.getdefaultencoding()\n\ndef our_encode(s, errors=\'strict\'):\n printWarning("Default encoding used");\n return (codecs.encode(s, originalencoding, errors), len(s))\n\ndef our_decode(s, errors=\'strict\'):\n printWarning("Default encoding used");\n return (codecs.decode(s, originalencoding, errors), len(s))\n\ndef our_search(name):\n if name == \'our_encoding\':\n return codecs.CodecInfo(\n name=\'our_encoding\',\n encode=our_encode,\n decode=our_decode);\n return None\n\n# register our search and set the default encoding:\ncodecs.register(our_search)\nreload(sys)\nsys.setdefaultencoding(\'our_encoding\')\nRun Code Online (Sandbox Code Playgroud)\n\n如果您在脚本开头导入此文件,那么您将看到隐式转换的警告:
\n\n#!python2\n# coding: utf-8\n\nimport ourencoding\n\nprint("test 1")\na = "hello " + u"world"\n\nprint("test 2")\na = "hello \xe2\x98\xba " + u"world"\n\nprint("test 3")\nb = u" ".join(["hello", u"\xe2\x98\xba"])\n\nprint("test 4")\nc = unicode("hello \xe2\x98\xba")\nRun Code Online (Sandbox Code Playgroud)\n\n输出:
\n\ntest 1\ntest 2\nDefault encoding used\n File "test.py", line 10, in <module>\n a = "hello \xe2\x98\xba " + u"world"\ntest 3\nDefault encoding used\n File "test.py", line 13, in <module>\n b = u" ".join(["hello", u"\xe2\x98\xba"])\ntest 4\nDefault encoding used\n File "test.py", line 16, in <module>\n c = unicode("hello \xe2\x98\xba")\nRun Code Online (Sandbox Code Playgroud)\n\n正如测试 1 所示,它并不完美,如果转换后的字符串仅包含 ASCII 字符,有时您不会看到警告。
\n| 归档时间: |
|
| 查看次数: |
746 次 |
| 最近记录: |