str python3_在python3中是否可以完全修复内置的str

本文探讨了在 Python3 中尝试修补内置的 `str` 类型以追踪其分配的问题。作者首先尝试将 `str` 替换为一个函数,但这导致了 `isinstance` 检查失败。接着,他们使用类的方法创建了一个 `StrAllocator`,这个方法在普通构造中可以工作,但在某些特定场景如 `logging` 和 `unittests` 中遇到错误。文章详细展示了遇到的 TypeError 并寻求解决方案。
摘要由CSDN通过智能技术生成

我正在尝试修补python的内置

str

为了追踪所有

STR

分配。我遇到了一些问题,想知道是否有人可以看到我做错了什么,或者这是否可能通过在蟒蛇3猴子修补本机?(以下代码在Python2.7.12中运行良好)

$ python

Python 3.5.2 (default, Nov 23 2017, 16:37:01)

[GCC 5.4.0 20160609] on linux

我第一次天真地试图修补

STR

好像是一个函数:

def patch_str_allocations():

old_str = str

def mystr(*args, **kwargs):

return old_str(*args, **kwargs)

builtins.str = mystr

def test():

logger = logging.getLogger(__name__)

patch_str_allocations()

logger.debug(str('test'))

但这当然会失败字符串用于的所有类型的操作

isinstance

logger.debug(route)

File "/usr/lib/python3.5/logging/__init__.py", line 1267, in debug

self._log(DEBUG, msg, args, **kwargs)

File "/usr/lib/python3.5/logging/__init__.py", line 1403, in _log

fn, lno, func, sinfo = self.findCaller(stack_info)

File "/usr/lib/python3.5/logging/__init__.py", line 1360, in findCaller

filename = os.path.normcase(co.co_filename)

File "/home/ubuntu/.virtualenvs/papm/lib/python3.5/posixpath.py", line 52, in normcase

if not isinstance(s, (bytes, str)):

TypeError: isinstance() arg 2 must be a type or tuple of types

然后我尝试了一种基于类的方法:

class StrAllocator(str):

oldstr = None

def __new__(cls, *args, **kwargs):

return StrAllocator.oldstr.__new__(cls, *args, **kwargs)

@property

def __class__(self):

return str

def patch_str_allocations():

StrAllocator.oldstr = str

builtins.str = StrAllocator

在正常的str构造中,这可以正常工作,但仍然遇到一些问题:

class StrAllocatorTestCase(unittest.TestCase):

def test_log(self):

t1 = str('t1')

logger = logging.getLogger(__name__)

patch_str_allocations()

t2 = str('t2')

print(type(t1))

print(type(t2))

print(isinstance(t1, str))

print(isinstance(t2, StrAllocator))

print(isinstance(t2, str))

logger.debug(str('test'))

$ nosetests tests.test_str_allocator:StrAllocatorTestCase.test_log -s

False

True

True

E

======================================================================

ERROR: test_log (tests.instruments.test_str_allocator.StrAllocatorTestCase)

----------------------------------------------------------------------

Traceback (most recent call last):

File "/vagrant_data/github.com/dm03514/python-apm/tests/instruments/test_str_allocator.py", line 30, in test_log

logger.debug(str('test'))

File "/usr/lib/python3.5/logging/__init__.py", line 1267, in debug

self._log(DEBUG, msg, args, **kwargs)

File "/usr/lib/python3.5/logging/__init__.py", line 1403, in _log

fn, lno, func, sinfo = self.findCaller(stack_info)

File "/usr/lib/python3.5/logging/__init__.py", line 1360, in findCaller

filename = os.path.normcase(co.co_filename)

File "/home/ubuntu/.virtualenvs/papm/lib/python3.5/posixpath.py", line 54, in normcase

"not '{}'".format(s.__class__.__name__))

TypeError: normcase() argument must be str or bytes, not 'str'

----------------------------------------------------------------------

Ran 1 test in 0.003s

以及在sre_编译

isstring

检查

File "/home/ubuntu/.virtualenvs/papm/lib/python3.5/site-packages/flask/app.py", line 1250, in decorator [0/9965]

self.add_url_rule(rule, endpoint, f, **options)

File "/home/ubuntu/.virtualenvs/papm/lib/python3.5/site-packages/flask/app.py", line 66, in wrapper_func

return f(self, *args, **kwargs)

File "/home/ubuntu/.virtualenvs/papm/lib/python3.5/site-packages/flask/app.py", line 1216, in add_url_rule

self.url_map.add(rule)

File "/home/ubuntu/.virtualenvs/papm/lib/python3.5/site-packages/werkzeug/routing.py", line 1215, in add

rule.bind(self)

File "/home/ubuntu/.virtualenvs/papm/lib/python3.5/site-packages/werkzeug/routing.py", line 687, in bind

self.compile()

File "/home/ubuntu/.virtualenvs/papm/lib/python3.5/site-packages/werkzeug/routing.py", line 751, in compile

self._regex = re.compile(regex, re.UNICODE)

File "/home/ubuntu/.virtualenvs/papm/lib/python3.5/re.py", line 224, in compile

return _compile(pattern, flags)

File "/home/ubuntu/.virtualenvs/papm/lib/python3.5/re.py", line 292, in _compile

raise TypeError("first argument must be string or compiled pattern")

TypeError: first argument must be string or compiled pattern

有人能看到丢失的东西吗?(除了我对描述符和python类的理解之外:p)

从REPL来看,上面的示例可以工作,但是在nose和unittests的上下文中不起作用…

â« ipython

Python 3.5.2 (default, Nov 23 2017, 16:37:01)

Type 'copyright', 'credits' or 'license' for more information

IPython 6.4.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]: import logging

In [2]: import builtins

In [3]: class StrAllocator(str):

...: oldstr = None

...:

...: def __new__(cls, *args, **kwargs):

...: return StrAllocator.oldstr.__new__(cls, *args, **kwargs)

...:

...: @property

...: def __class__(self):

...: return str

...:

...:

In [4]: def patch_str_allocations(): [6/9733]

...: StrAllocator.oldstr = str

...: builtins.str = StrAllocator

...:

In [5]: def test_log():

...: t1 = str('t1')

...: logger = logging.getLogger(__name__)

...: patch_str_allocations()

...: t2 = str('t2')

...: print(type(t1))

...: print(type(t2))

...: print(isinstance(t1, str))

...: print(isinstance(t2, StrAllocator))

...: print(isinstance(t2, str))

...: logger.debug(str('test'))

...:

In [6]: test_log()

False

True

True

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值