2013-03-18 75 views
1

假設我們有一個有錯誤的一段代碼意外地覆蓋一些系統庫的屬性,就像這樣:如何避免在Python中覆蓋系統庫的屬性?

import socket 
socket.error = 'some other object' 

有什麼辦法來防止這種行爲,或找負責做的代碼?

我試圖使一個地產出socket.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) 

然後設置屬性:

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) 
+1

你能不能用grep的調皮線? '$ grep -r'socket.error ='*' – danodonovan 2013-03-18 16:51:51

+1

真的,這在生產代碼中很少發生。當它發生時,你會很快發現它,並且grep是你的朋友。 – 2013-03-18 16:52:34

+1

grep沒有找到任何東西。淘氣的線路可能就像'襪子的導入插座; x ='錯誤'; setattr(sock,x,'其他對象')' – 2013-03-18 16:53:33

回答

6

你可以(暫時)在你的代碼粘貼此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 
+2

這不起作用,因爲如果你從另一個地方運行'import socket'文件名將顯示系統庫,而不是創建的網橋。 – 2013-03-18 17:07:50

+0

@delnan - 這是正確的,但sys.modules將不包含對Bridge實例的引用,而是對系統庫的引用。 Bridge實例的實際引用只能從您定義的位置看到。也許還可以將它粘貼到sys.modules中? – 2013-03-18 17:10:46

+2

@MihneaGiurgea:好點。設置'sys.modules ['socket'] =橋(套接字)'將解決這個問題。 – unutbu 2013-03-18 17:14:41