例如,實現了乙個telnet客戶端的類telnetclient,呼叫例項的connect()
、login()
、interact()
方法啟動客戶端與伺服器互動,互動完畢後呼叫cleanup()
方法關閉已連線的socket,以及將操作歷史記錄寫入檔案並關閉。
要求:讓telnetclient的例項支援上下文管理協議,從而替代手動呼叫connect()
、cleanup()
方法。
解決方案:
實現上下文管理協議,即實現類的__enter__()
、__exit__()
方法,它們分別在with開始和結束時別呼叫。
with所求值的物件必須有乙個__enter__()
方法和乙個__exit__()
方法。
緊跟with後面的語句被求值後,返回物件的__enter__()
方法被呼叫,這個方法的返回值將被賦值給as後面的變數。當with後面的**塊全部被執行完之後,將呼叫前面返回物件的__exit__()
方法。
# yum install -y telnet-server
# systemctl start telnet.socket
from sys import stdin, stdout
import getpass
import telnetlib
from collections import deque
class
telnetclient
:def
__init__
(self, host, port=23)
: self.host = host
self.port = port
defconnect
(self)
: self.tn = telnetlib.telnet(self.host, self.port)
self.history = deque(
)def
cleanup
(self)
: self.tn.close(
) self.tn =
none
with
open
('history.txt'
,'a'
)as f:
f.writelines(self.history)
deflogin
(self)
:# user
self.tn.read_until(b"login: "
) user =
input
("enter your remote account: "
) self.tn.write(user.encode(
'utf8'
)+ b"\n"
)# password
self.tn.read_until(b"password: "
) password = getpass.getpass(
) self.tn.write(password.encode(
'utf8'
)+ b"\n"
) out = self.tn.read_until(b'$ '
) stdout.write(out.decode(
'utf8'))
definteract
(self)
:while
true
: cmd = stdin.readline()if
not cmd:
break
self.tn.write(cmd.encode(
'utf8'))
out = self.tn.read_until(b'$ '
).decode(
'utf8'
) stdout.write(out[
len(cmd)+1
:]) stdout.flush(
)client = telnetclient(
'192.168.30.128'
)client.connect(
)client.login(
)client.interact(
)client.cleanup(
)
上面是手工呼叫connect()
及cleanup()
方法。使用with ... as ...
語句上下文管理:
from sys import stdin, stdout
import getpass
import telnetlib
from collections import deque
class
telnetclient
:def
__init__
(self, host, port=23)
: self.host = host
self.port = port
def__enter__
(self)
: self.tn = telnetlib.telnet(self.host, self.port)
self.history = deque(
)return self
def__exit__
(self, exc_type, exc_value, exc_tb)
:print
('in __exit__'
, exc_type, exc_value, exc_tb)
self.tn.close(
) self.tn =
none
with
open
('history.txt'
,'a'
)as f:
f.writelines(self.history)
return
true
#將錯誤壓制在方法內部,不再拋給上層
deflogin
(self)
:# user
self.tn.read_until(b"login: "
) user =
input
("enter your remote account: "
) self.tn.write(user.encode(
'utf8'
)+ b"\n"
)# password
self.tn.read_until(b"password: "
) password = getpass.getpass(
) self.tn.write(password.encode(
'utf8'
)+ b"\n"
) out = self.tn.read_until(b'$ '
) stdout.write(out.decode(
'utf8'))
definteract
(self)
:while
true
: cmd = stdin.readline()if
not cmd:
break
self.tn.write(cmd.encode(
'utf8'))
out = self.tn.read_until(b'$ '
).decode(
'utf8'
) stdout.write(out[
len(cmd)+1
:]) stdout.flush(
)with telnetclient(
'192.168.30.128'
)as client:
raise exception(
'test'
)#生成錯誤資訊
client.login(
) client.interact(
)print
('end'
)
with真正強大之處是它可以處理異常。可能你已經注意到類的__exit__()
方法有三個引數:exc_type, exc_value, exc_tb。在with後面的**塊丟擲任何異常時,__exit__()
方法被執行。 讓物件支援上下文管理協議
問題 你想讓你的物件支援上下文管理協議 with語句 解決方案 為了讓乙個物件相容 with 語句,你需要實現enter 和exit 方法。例如,考慮如下的乙個類,它能為我們建立乙個網路連線 from socket import socket,af inet,sock stream class la...
python類與物件 如何讓物件支援上下文管理
問題舉例 乙個telnet客戶端的類telnetclient,呼叫例項的connect login interact方法 啟動客戶端與伺服器互動,互動完畢後需要呼叫cleanup 方法,關閉已連線的socket,以及將操作歷史記錄寫入檔案並關閉。能否讓telnetclient的例項支援上下文管理協議...
上下文物件
ps 好久沒更新了,我把知識點都寫在了文件上,別急以後可能一天會更新好多條,哈哈哈 一 上下文概念 每乙個web project,執行時都部署在tomcat下,稱為乙個應用。部署後,啟動tomcat時,tomcat將為每乙個應用建立乙個物件,這個物件稱之為上下文物件。乙個應用有且只有乙個上下文物件,...