如何避免在Python中重写系统库的属性?

如何避免在Python中重写系统库的属性?,python,python-module,Python,Python Module,假设我们有一段错误代码,它意外地覆盖了某个系统库的属性,如下所示: import socket socket.error = 'some other object' 有没有办法防止这种行为,或者找到负责这种行为的代码 我尝试使用socket.error创建属性,但不起作用: def fget(self): return socket.error def fset(self, value): raise SystemError('You cannot alter this at

假设我们有一段错误代码,它意外地覆盖了某个系统库的属性,如下所示:

import socket
socket.error = 'some other object'
有没有办法防止这种行为,或者找到负责这种行为的代码

我尝试使用socket.error创建属性,但不起作用:

def fget(self):
    return socket.error

def fset(self, value):
    raise SystemError('You cannot alter this attribute.')

# From now on, settings socket.error = x should raise an error
socket.error = property(fget, fset)
您可以(暂时)在代码中保留以下内容:

class Bridge(object):
    def __init__(self, module):
        self.__dict__['module'] = module
    def __getattr__(self, attr):
        return getattr(self.module, attr)
    def __setattr__(self, attr, val):
        raise TypeError('{a!r} can not be set'.format(a=attr))

import sys
import socket
socket = sys.modules['socket'] = Bridge(socket)
然后在
socket
上设置属性(至少以最常用的方式)将引发异常。回溯将允许您定位错误

print(socket.error)
setattr(socket, 'error', 'blah')
屈服

% test.py
<class 'socket.error'>
Traceback (most recent call last):
  File "/home/unutbu/pybin/test.py", line 15, in <module>
    setattr(socket, 'error', 'blah')
  File "/home/unutbu/pybin/test.py", line 10, in __setattr__
    raise TypeError('{a!r} can not be set'.format(a=attr))
TypeError: 'error' can not be set
%test.py
回溯(最近一次呼叫最后一次):
文件“/home/unutbu/pybin/test.py”,第15行,在
setattr(套接字,'error','blah')
文件“/home/unutbu/pybin/test.py”,第10行,在__
raise TypeError({a!r}无法设置)。格式(a=attr))
TypeError:无法设置“error”
您可以(暂时)在代码中粘贴以下内容:

class Bridge(object):
    def __init__(self, module):
        self.__dict__['module'] = module
    def __getattr__(self, attr):
        return getattr(self.module, attr)
    def __setattr__(self, attr, val):
        raise TypeError('{a!r} can not be set'.format(a=attr))

import sys
import socket
socket = sys.modules['socket'] = Bridge(socket)
然后在
socket
上设置属性(至少以最常用的方式)将引发异常。回溯将允许您定位错误

print(socket.error)
setattr(socket, 'error', 'blah')
屈服

% test.py
<class 'socket.error'>
Traceback (most recent call last):
  File "/home/unutbu/pybin/test.py", line 15, in <module>
    setattr(socket, 'error', 'blah')
  File "/home/unutbu/pybin/test.py", line 10, in __setattr__
    raise TypeError('{a!r} can not be set'.format(a=attr))
TypeError: 'error' can not be set
%test.py
回溯(最近一次呼叫最后一次):
文件“/home/unutbu/pybin/test.py”,第15行,在
setattr(套接字,'error','blah')
文件“/home/unutbu/pybin/test.py”,第10行,在__
raise TypeError({a!r}无法设置)。格式(a=attr))
TypeError:无法设置“error”

你能帮我记下这句顽皮的台词吗<代码>$grep-r'socket.error='*实际上,这种情况在生产代码中很少发生。当它真的发生时,你会很快找到答案,而grep是你的朋友。grep什么也没发现。顽皮的线条可能类似于
importsocketassock;x='错误';setattr(sock,x,‘其他对象’)
然后使用二进制搜索。禁用一半代码,查看是否设置了
error
。如果没有,则切换禁用的内容。如果是这样的话,关注这一半并再次禁用这一半。Wash,rince,repeat.作为旁注,您的尝试失败的原因是
属性
创建了描述符,这些描述符只在类中有效,在模块中无效。(这有点过于简单,几乎是在撒谎……但是如果不解释属性查找在新样式的类实例中是如何工作的,我不知道更好的说法。如果你想要真正的解释,请阅读,特别是3.4.2.3。)你能为这句顽皮的话而高兴吗<代码>$grep-r'socket.error='*
实际上,这种情况在生产代码中很少发生。当它真的发生时,你会很快找到答案,而grep是你的朋友。grep什么也没发现。顽皮的线条可能类似于
importsocketassock;x='错误';setattr(sock,x,‘其他对象’)
然后使用二进制搜索。禁用一半代码,查看是否设置了
error
。如果没有,则切换禁用的内容。如果是这样的话,关注这一半并再次禁用这一半。Wash,rince,repeat.作为旁注,您的尝试失败的原因是
属性
创建了描述符,这些描述符只在类中有效,在模块中无效。(这有点过于简单,几乎是在撒谎……但是如果不解释属性查找在新样式的类实例中是如何工作的,我不知道更好的说法。如果你想要真正的解释,请阅读,特别是3.4.2.3。)这行不通,因为如果从另一个文件名运行
import socket
,将看到系统库,而不是创建的桥。@delnan-这是正确的,但是sys.modules将不包含对桥实例的引用,而是对系统库的引用。对桥实例的实际引用将仅在定义它的位置可见。也许还可以把它放在系统模块里?@MihneaGiurgea:说得对。设置
sys.modules['socket']=Bridge(socket)
将修复此问题。这不起作用,因为如果从另一个文件名运行
import socket
,将看到系统库,而不是创建的桥。@delnan-这是正确的,但sys.modules将不包含对桥实例的引用,而是对系统库的引用。对桥实例的实际引用将仅在定义它的位置可见。也许还可以把它放在系统模块里?@MihneaGiurgea:说得对。设置
sys.modules['socket']=Bridge(socket)
将解决这个问题。