32 讓物件支援上下文管理

2021-10-01 23:47:50 字數 4430 閱讀 1077

例如,實現了乙個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將為每乙個應用建立乙個物件,這個物件稱之為上下文物件。乙個應用有且只有乙個上下文物件,...