python pp模块_Python模块--Pexpect
探索 Pexpect,第 1 部分:剖析 Pexpect
概述
Pexpect 是 Don Libes 的?Expect 語言的一個 Python 實現,是一個用來啟動子程序,并使用正則表達式對程序輸出做出特定響應,以此實現與其自動交互的 Python 模塊。 Pexpect 的使用范圍很廣,可以用來實現與 ssh、ftp 、telnet 等程序的自動交互;可以用來自動復制軟件安裝包并在不同機器自動安裝;還可以用來實現軟件測試中與命令行交互的自動化。
下載
Pexpect 可以從?SourceForge?網站下載。 本文介紹的示例使用的是 2.3 版本,如不說明測試環境,默認運行操作系統為 fedora 9 并使用 Python 2.5 。
安裝
依賴
Python 版本 2.4 或者 2.5
pty module ,pty 是任何 Posix 系統標準庫的一部分
由于其依賴 pty module ,所以 Pexpect 還不能在 Windows 的標準 python 環境中執行,如果想在 Windows 平臺使用,可以使用在 Windows 中運行 Cygwin 做為替代方案。
遵循 MIT 許可證
根據 Wiki 對 MIT License 的介紹“該模塊被授權人有權利使用、復制、修改、合并、出版發行、散布、再授權及販售軟件及軟件的副本。被授權人可根據程序的需要修改授權條款為適當的內容。在軟件和軟件的所有副本中都必須包含版權聲明和許可聲明。”
Pexpect 提供的 run() 函數:
清單 1. run() 的定義
函數 run 可以用來運行命令,其作用與 Python os 模塊中 system() 函數相似。run() 是通過?Pexpect類實現的。
如果命令的路徑沒有完全給出,則 run 會使用 which 命令嘗試搜索命令的路徑 。
清單 2. 使用 run()執行 svn 命令
與 os.system() 不同的是,使用 run() 可以方便地同時獲得命令的輸出結果與命令的退出狀態 。
清單 3. run() 的返回值
command_out 中保存的就是 /bin 目錄下的內容。
Pexpect 提供的 spawn() 類:
使用 Pexpect 啟動子程序
清單 4. spawn 的構造函數
spawn是Pexpect模塊主要的類,用以實現啟動子程序,它有豐富的方法與子程序交互從而實現用戶對子程序的控制。它主要使用 pty.fork() 生成子進程,并調用 exec() 系列函數執行 command 參數的內容。
可以這樣使用:
清單 5. spawn() 使用示例
當子程序需要參數時,還可以使用一個參數的列表:
清單 6. 參數列表示例
在構造函數中,maxread 屬性指定了 Pexpect 對象試圖從 tty 一次讀取的最大字節數,它的默認值是2000字節 。
由于需要實現不斷匹配子程序輸出, searchwindowsize 指定了從輸入緩沖區中進行模式匹配的位置,默認從開始匹配。
logfile 參數指定了 Pexpect 產生的日志的記錄位置。
例如:
清單 7. 記錄日志
還可以將日志指向標準輸出:
清單 8. 將日志指向標準輸出
如果不需要記錄向子程序輸入的日志,只記錄子程序的輸出,可以使用:
清單 9. 記錄輸出日志
使用 Pexpect 控制子程序
為了控制子程序,等待子程序產生特定輸出,做出特定的響應,可以使用 expect 方法。
清單 10. expect() 定義
在參數中: pattern 可以是正則表達式, pexpect.EOF , pexpect.TIMEOUT ,或者由這些元素組成的列表。需要注意的是,當 pattern 的類型是一個列表時,且子程序輸出結果中不止一個被匹配成功,則匹配返回的結果是緩沖區中最先出現的那個元素,或者是列表中最左邊的元素。使用 timeout 可以指定等待結果的超時時間 ,該時間以秒為單位。當超過預訂時間時, expect 匹配到pexpect.TIMEOUT。
如果難以估算程序運行的時間,可以使用循環使其多次等待直至等待運行結束:
清單 11. 使用循環
expect() 在執行中可能會拋出兩種類型的異常分別是 EOF and TIMEOUF,其中 EOF 通常代表子程序的退出, TIMEOUT 代表在等待目標正則表達式中出現了超時。
清單 12. 使用并捕獲異常
此時可以將這兩種異常放入expect等待的目標列表中:
清單 13. 避免異常
expect 不斷從讀入緩沖區中匹配目標正則表達式,當匹配結束時 pexpect 的 before 成員中保存了緩沖區中匹配成功處之前的內容, pexpect 的 after 成員保存的是緩沖區中與目標正則表達式相匹配的內容。
清單 14. 打印 before 成員的內容
此時 child.before 保存的就是在根目錄下執行 ls 命令的結果。
清單 15. send 系列函數
這些方法用來向子程序發送命令,模擬輸入命令的行為。 與 send() 不同的是 sendline() 會額外輸入一個回車符 ,更加適合用來模擬對子程序進行輸入命令的操作。 當需要模擬發送 “Ctrl+c” 的行為時,還可以使用 sendcontrol() 發送控制字符。
清單 16. 發送 ctrl+c
由于 send() 系列函數向子程序發送的命令會在終端顯示,所以也會在子程序的輸入緩沖區中出現,因此不建議使用 expect 匹配最近一次 sendline() 中包含的字符。否則可能會在造成不希望的匹配結果。
清單 17. interact() 定義
Pexpect還可以調用interact() 讓出控制權,用戶可以繼續當前的會話控制子程序。用戶可以敲入特定的退出字符跳出,其默認值為“^]” 。
下面展示一個使用Pexpect和ftp交互的實例。
清單 18. ftp 交互的實例:
該程序與 ftp 做交互,登錄到 ftp.openbsd.org ,當提述輸入登錄名稱和密碼時輸入默認用戶名和密碼,當出現 “ftp>” 這一提示符時切換到 pub/OpenBSD 目錄并下載 README 這一文件。
以下實例是上述方法的綜合應用,用來建立一個到遠程服務器的 telnet 連接,并返回保存該連接的 pexpect 對象。
清單 19. 登錄函數:
Pxssh 類的使用:
Pxssh 做為 pexpect 的派生類可以用來建立一個 ssh 連接,它相比其基類增加了如下方法:
login() 建立到目標機器的ssh連接 ;
losuckgout() 釋放該連接 ;
prompt() 等待提示符,通常用于等待命令執行結束。
下面的示例連接到一個遠程服務器,執行命令并打印命令執行結果。
該程序首先接受用戶輸入用戶名和密碼,login 函數返回一個 pxssh 對象的鏈接,然后調用 sendline() 分別輸入 “uptime”、“ls” 等命令并打印命令輸出結果。
清單 20. pxssh 示例
Pexpect 使用中需要注意的問題:
spawn() 參數的限制
在使用spawn執行命令時應該注意,Pexpect 并不與 shell 的元字符例如重定向符號 > 、>> 、管道 | ,還有通配符 * 等做交互,所以當想運行一個帶有管道的命令時必須另外啟動一個 shell ,為了使代碼清晰,以下示例使用了參數列表例如:
清單 21. 啟動新的 shell 執行命令
與線程共同工作
Perl 也有 expect 的模塊?Expect-1.21,但是 perl 的該模塊在某些操作系統例如 fedora 9 或者 AIX 5 中不支持在線程中啟動程序執行以下實例試圖利用多線同時程登錄到兩臺機器進行操作,不使用線程直接調用時 sub1() 函數可以正常工作,但是使用線程時在 fedora9 和 AIX 5 中都不能正常運行。
清單 22. perl 使用 expect 由于線程和 expect 共同使用導致不能正常工作的程序
Pexpect 則沒有這樣的問題,可以使用多線程并在線程中啟動程序運行。但是在某些操作系統如 fedora9 中不可以在線程之間傳遞 Pexpect 對象。
清單 使用 Pexpect 在線程中啟動控制子程序
應用實例:
在實際系統管理員的任務中,有時需要同時管理多臺機器,這個示例程序被用來自動編譯并安裝新的內核版本,并重啟。它使用多線程,每個線程都建立一個到遠程機器的 telnet 連接并執行相關命令。 該示例會使用上文中的登錄函數。
清單 23. 管理多臺機器示例
相關主題
訪問?Expect?的主頁,了解更多 Expect 的內容。
參考?Wiki?上關于 MIT 許可證的介紹。
查看文章“ Expect 在網絡管理中發揮著重要作用”介紹 Expect 在網絡管理中的應用。
Perl 語言中的 Expect?了解 Perl 語言中的 Expect 。
在 developerWorks 上查閱所有?Linux 技巧和?Linux 教程。
探索 Pexpect,第 2 部分:Pexpect 的實例分析
概述
通過本系列第一部分《探索 Pexpect,第 1 部分:剖析 Pexpect 》(請參閱參考資料)的介紹,相信大家已經對 Pexpect 的用法已經有了比較全面的了解,知道 Pexpect 是個純 Python 語言實現的模塊,使用其可以輕松方便的實現與 ssh、ftp、passwd 和 telnet 等程序的自動交互,但是讀者的理解還可能只是停留在理論基礎上,本文將從實際例子入手具體介紹 Pexpect 的使用場景和使用心得體驗,實例中的代碼讀者都可以直接拿來使用,相信會對大家產生比較大的幫助。 以下是本文所要介紹的所有 Pexpect 例子標題:
例 1:ftp 的使用(注:spawn、expect 和 sendline 的使用)
例 2:記錄 log(注:logfile、logfile_send和logfile_read的使用)
例 3:ssh 的使用
例 4:pxssh 的使用
例 5:telnet 的使用(注:interact 的使用)
pexpect 使用 tips
調試 pexpect 程序的 tips
pexpect 不會解釋 shell 中的元字符
EOF 異常和 TIMEOUT 異常
使用 run() 來替代某些的 spawn 的使用
expect_exact() 的使用
expect() 中正則表達式的使用 tips
isalive() 的使用 tips
delaybeforesend 的使用 tips
例 1:ftp 的使用
本例實現了如下功能:ftp 登錄到 develperWorks.ibm.com 主機上,并用二進制傳輸模式下載一個名叫 rmall的文件。
清單 1. ftp 的例子代碼
注:
運行后,輸出結果為:
本例 expect 函數中的 pattern 使用了 List,并包含了 pexpect.EOF和pexpect.TIMEOUT,這樣出現了超時或者 EOF,不會拋出 expection 。(關于 expect() 函數的具體使用,請參閱參考資料)
如果程序運行中間出現了錯誤,如用戶名密碼錯誤,超時或者 EOF,遠程 server 連接不上,都會使用 c hild.close(force=True) 關掉 ftp 子程序。調用 close 可以用來關閉與子程序的 connection 連接,如果你不僅想關閉與子程序的連接,還想確保子程序是真的被 terminate 終止了,設置參數 force=True,其最終會調用 c hild.kill(signal.SIGKILL) 來殺掉子程序。
例 2:記錄 log
本例實現了如下功能:運行一個命令,并將該命令的運行輸出結果記錄到 log 文件中 ./command.py [-a] [-c command] {logfilename} -c 后接的是要運行的命令的名字,默認是“ls -l”; logfilename 是記錄命令運行結果的 log 文件名,默認是“command.log”;指定 -a 表示命令的輸出結果會附加在 logfilename 后,如果 logfilename 之前已經存在的話。
清單 2. 記錄 log 的例子代碼
注:
運行:./command.py -a -c who cmd.log
logfile:
只能通過 spawn 類的構造函數指定。在 spawn 類的構造函數通過參數指定 logfile 時,表示開啟或關閉 logging 。所有的子程序的 input 和 output 都會被 copy 到指定的 logfile 中。設置 logfile 為 None 表示停止 logging,默認就是停止 logging 。設置 logfile 為 sys.stdout,會將所有東西 echo 到標準輸出。
logfile_read和logfile_send:
logfile_read:只用來記錄 python 主程序接收到 child 子程序的輸出,有的時候你不想看到寫給 child 的所有東西,只希望看到 child 發回來的東西。 logfile_send:只用來記錄 python 主程序發送給 child 子程序的輸入 logfile、logfile_read 和 logfile_send 何時被寫入呢? logfile、logfile_read 和 logfile_send 會在每次寫 write 和 send 操作后被 flush 。
調用 send 后,才會往 logfile 和 logfile_send 中寫入,sendline/sendcontrol/sendoff/write/writeline 最終都會調用 send,所以 sendline 后 logfile 中一定有內容了,只要此時 logfile 沒有被 close 。
調用 read_nonblocking 后,才會往 logfile 和 logfile_read 中寫入,expect_loop 會調用 read_nonblocking,而 expect_exact 和 expect_list 都會調用 expect_loop,expect 會調用 expect_list,所以 expect 后 logfile 中一定有內容了,只要此時 logfile 沒有被 close 。
如果調用的函數最終都沒有調用 send 或 read_nonblocking,那么 logfile 雖然被分配指定了一個 file,但其最終結果是:內容為空。見下例:
清單 3. log 內容為空的例子代碼
運行該腳本后,你會發現其實 log.txt 是空的,沒有記錄 ls -l 命令的內容,原因是沒有調用 send 或 read_nonblocking,真正的內容沒有被 flush 到 log 中。如果在 fout.close() 之前加上 p.expect(pexpect.EOF),log.txt 才會有 ls -l 命令的內容。
例 3:ssh 的使用
本例實現了如下功能:ssh 登錄到某個用戶指定的主機上,運行某個用戶指定的命令,并輸出該命令的結果。
清單 4. ssh 的例子代碼
注:
運行后,輸出結果為:
使用了 getpass.getpass() 來獲得用戶輸入的密碼,與 raw_input 不同的是,getpass.getpass() 不會將用戶輸入的密碼字符串 echo 回顯到 stdout 上。(更多 python 相關技術,請參閱參考資料)
例 4:pxssh 的使用
本例實現了如下功能:使用 pexpect 自帶的 pxssh 模塊實現 ssh 登錄到某個用戶指定的主機上,運行命令’ uptime ’和’ ls -l ’,并輸出該命令的結果。
清單 5. 使用 pxssh 的例子代碼
運行后,輸出結果為:
pxssh 是 pexpect 中 spawn 類的子類,增加了 login, logout 和 prompt 幾個方法,使用其可以輕松實現 ssh 連接,而不用自己調用相對復雜的 pexpect 的方法來實現。 pxssh 做了很多 tricky 的東西來處理 ssh login 過程中所可能遇到的各種情況。比如:如果這個 session 是第一次 login,pxssh 會自動接受遠程整數 remote certificate ;如果你已經設置了公鑰認證,pxssh 將不會再等待 password 的提示符。(更多 ssh 相關知識,請參閱參考資料) pxssh 使用 shell 的提示符來同步遠程主機的輸出,為了使程序更加穩定,pxssh 還可以設置 prompt 為更加唯一的字符串,而不僅僅是“ $ ”和“ # ”。
login?方法
使用原始 original_prompt 來找到 login 后的提示符(這里默認 original_prompt 是“$”或“#”,但是有時候可能也是別的 prompt,這時就需要在 login 時手動指定這個特殊的 prompt,見上例,有可能是“ > ”),如果找到了,立馬使用更容易匹配的字符串來重置該原始提示符(這是由 pxssh 自己自動做的,通過命令 "PS1='[PEXPECT]\$ '" 重置原始提示符,然后每次 expect 匹配 \[PEXPECT\][\$\#])。原始提示符是很容易被混淆和胡弄的,為了阻止錯誤匹配,最好根據特定的系統,指定更加精確的原始提示符,例如 "Message Of The Day" 。 有些情況是不允許重置原始提示符的,這時就要設置 auto_prompt_reset 為 False 。而且此時需要手動設置 PROMPT 域為某個正則表達式來 match 接下來要出現的新提示符,因為 prompt() 函數默認是 expect 被重置過的 PROMPT 的。
prompt方法
匹配新提示符(不是 original_prompt)。注:這只是匹配提示符,不能匹配別的 string,如果要匹配特殊 string,需直接使用父類 spawn 的 expect 方法。 prompt 方法相當于是 expect 方法的一個快捷方法。如果auto_prompt_reset 為 False,這時需要手動設置 PROMPT 域為某個正則表達式來 match 接下來要出現的 prompt,因為 prompt() 函數默認是 expect 被重置過的 PROMPT 的。
logout方法
發送'exit'給遠程 ssh 主機,如果有 stopped jobs,會發送'exit'兩次。
例 5:telnet 的使用
本例實現了如下功能:telnet 登錄到某遠程主機上,輸入命令“ls -l”后,將子程序的執行權交還給用戶,用戶可以與生成的 telnet 子程序進行交互。
清單 6. telnet 的例子代碼
運行后,輸出結果為:
interact方法
通常一個 python 主程序通過 pexpect.spawn 啟動一個子程序,一旦該子程序啟動后,python 主程序就可以通過 child.expect 和 child.send/child.sendline 來和子程序通話,python 主程序運行結束后,子程序也就死了。比如 python 主程序通過 pexpect.spawn 啟動了一個 telnet 子程序,在進行完一系列的 telnet 上的命令操作后,python 主程序運行結束了,那么該 telnet session(telnet 子程序)也會自動退出。但是如果調用 child.interact,那么該子程序(python 主程序通過 pexpect.spawn 衍生成的)就可以在運行到 child.interact 時,將子程序的控制權交給了終端用戶(the human at the keyboard),用戶可以通過鍵盤的輸入來和子程序進行命令交互,管理子程序的生殺大權,用戶的鍵盤輸入 stdin 會被傳給子程序,而且子程序的 stdout 和 stderr 輸出也會被打印出來到終端。 默認 ctrl + ] 退出 interact() 模式,把子程序的執行權重新交給 python 主程序。參數 escape_character 指定了交互模式的退出字符,例如 child.interact(chr(26)) 接下來就會變成 ctrl + z 退出 interact() 模式。
pexpect 使用 tips
調試 pexpect 程序的 tips
獲得 pexpect.spawn 對象的字符串 value值,將會給 debug 提供很多有用信息。
清單 7. 打印 pexpect.spawn 對象的字符串 value 值的例子代碼
將子程序的 input 和 output 打 log 到文件中或者直接打 log 到屏幕上也非常有用
清單 8. 記錄 log 的例子代碼
pexpect 不會解釋 shell 中的元字符
pexpect 不會解釋 shell 的元字符,如重定向 redirect,管道 pipe,和通配符 wildcards( “ > ” , “ | ”和“ * ”等 ) 如果想用的話,必須得重新啟動一個新 shell(在 spawn 的參數 command 中是不會解釋他們的,視其為 command string 的一個普通字符)
清單 9. 重新啟動一個 shell 來規避 pexpect 對元字符的不解釋
如果想在 spawn 出來的新子程序中使用重定向 redirect,管道 pipe,和通配符 wildcards( “ > ” , “ | ”和“ * ”等 ),好像沒有好的方法,只能不使用這些字符,先利用 expect 匹配命令提示符,從而在 before 中可以拿到之前命令的結果,然后在分析 before 的內容達到使用重定向 redirect, 管道 pipe, 和通配符 wildcards 的目的。
EOF 異常和 TIMEOUT 異常
TIMEOUT 異常
如果子程序沒有在指定的時間內生成任何 output,那么 expect() 和 read() 都會產生 TIMEOUT 異常。超時默認是 30s,可以在 expect() 和 spawn 構造函數初始化時指定為其它時間,如:
如果你想讓 expect() 和 read() 忽略超時限制,即無限期阻塞住直到有 output 產生,設置 timeout 參數為 None。
清單 10. 忽略 timeout 超時限制的例子代碼
EOF 異常
可能會有兩種 EOF 異常被拋出,但是他們除了顯示的信息不同,其實本質上是相同的。為了實用的目的,不需要區分它們,他們只是給了些關于你的 python 程序到底運行在哪個平臺上的額外信息,這兩個顯示信息是:
有些 UNIX 平臺,當你讀取一個處于 EOF 狀態的文件描述符時,會拋出異常,其他 UNIX 平臺,卻只會靜靜地返回一個空字符串來表明該文件已經達到了狀態。
使用 run() 來替代某些的 spawn 的使用
pexpect 模塊除了提供 spawn 類以外,還提供了 run() 函數,使用其可以取代一些 spawn 的使用,而且更加簡單明了。
清單 11. 使用 run() 來替代 spawn 的使用的例子代碼
run (command, timeout=-1, withexitstatus=False, events=None, extra_args=None, logfile=None, cwd=None, env=None):
command:執行一個命令,然后返回結果,run() 可以替換 os.system()(更多 os.system() 知識,請參閱參考資料),因為 os.system() 得不到命令輸出的結果
返回的 output 是個字符串,STDERR 也會包括在 output 中,如果全路徑沒有被指定,那么 path 會被 search
timeout:單位 s 秒,每隔 timeout 生成一個 pexpect.TIMEOUT 異常
每行之間被 CR/LF (\\r\\n) 相隔,即使在 Unix 平臺上也是 CR/LF,因為 Pexpect 子程序是偽 tty 設備
withexitstatus:設置為 True,則返回一個 tuple,里面包括 (command_output, exitstatus),如果其為 False,那么只是僅僅返回 command_output
events:是個 dictionary,里面存放 {pattern:response} 。無論什么時候 pattern 在命令的結果中出現了,會出現以下動作:
發送相應的 response String 。如果需要回車符“ Enter ”的話,“ \\n ”也必須得出現在 response 字符串中。
response 同樣也可以是個回調函數,不過該回調函數有特殊要求,即它的參數必須是個 dictionary,該 dictionary 的內容是:包含所有在 run() 中定義的局部變量,從而提供了方法可以訪問 run() 函數中 spawn 生成的子程序和 run() 中定義的其他局部變量,其中 event_count, child, 和 extra_args 最有用。回調函數可能返回 True,從而阻止當前 run() 繼續執行,否則 run() 會繼續執行直到下一個 event 。回調函數也可能返回一個字符串,然后被發送給子程序。 'extra_args' 不是直接被 run() 使用,它只是提供了一個方法可以通過 run() 來將數據傳入到回調函數中(其實是通過 run() 定義的局部變量 dictionary 來傳)
清單 12. 其它一些使用 run() 的例子代碼
expect_exact() 的使用
expect_exact(self, pattern_list, timeout = -1, searchwindowsize = -1); expect_exact() 與 expect() 類似,但是 pattern_list 只能是字符串或者是一個字符串的 list,不能是正則表達式,其匹配速度會快于 expect(),原因有兩個:一是字符串的 search 比正則表達式的匹配要快,另一個則是可以限制只從輸入緩沖的結尾來尋找匹配的字符串。還有當你覺得每次要 escape 正則表達式中的特殊字符為普通字符時很煩,那么你也可以使用 expect_exact() 來取代 expect()。
清單 13. expect_exact() 的例子代碼
expect() 中正則表達式的使用 tips
expect() 中的正則表達式不是貪婪匹配 greedy match,而是最小匹配,即只匹配緩沖區中最早出現的第一個字符串。 因為是依次讀取一個字符的 stream 流來判斷是否和正則表達式所表達的模式匹配,所以如果參數 pattern 是個 list,而且不止一次匹配,那么緩沖區中最早出現的第一個匹配的字符串才算數。
清單 14. expect() 的最小匹配例子代碼
“$”不起任何作用,匹配一行的結束 (end of line),必須得匹配 CR/LF
正則表達式中,'$'可以匹配一行的結束(具體'$'正則表達式的使用,請參閱參考資料),但是 pexpect 從子程序中一次只讀取一個字符,而且每個字符都好像是一行的結束一樣,pexpect 不能在子程序的輸出流去預測。匹配一行結束的方法必須是匹配 "\r\n" (CR/LF) 。即使是 Unix 系統,也是匹配 "\r\n" (CR/LF),因為 pexpect 使用一個 Pseudo-TTY 設備與子程序通話,所以當子程序輸出 "\n" 你仍然會在 python 主程序中看到 "\r\n" 。原因是 TTY 設備更像 windows 操作系統,每一行結束都有個 "\r\n" (CR/LF) 的組合,當你從 TTY 設備去解釋一個 Unix 的命令時,你會發現真正的輸出是 "\r\n" (CR/LF),一個 Unix 命令只會寫入一個 linefeed (\n),但是 TTY 設備驅動會將其轉換成 "\r\n" (CR/LF) 。
清單 15. 匹配一行結束 1
如果你只是想跳過一個新行,直接 expect('\n') 就可以了,但是如果你想在一行的結束匹配一個具體的 pattern 時,就必須精確的尋找 (\r),見下例:
清單 16. 匹配一行結束 2
這個問題其實不只是 pexpect 會有,如果你在一個 stream 流上實施正則表達式匹配時,都會遇到此問題。正則表達式需要預測,stream 流中很難預測,因為生成這個流的進程可能還沒有結束,所以你很難知道是否該進程是暫時性的暫停還是已經徹底結束。
當 '.' 和 '*' 出現在最后時
child.expect ('.+'); 因為是最小匹配,所以只會返回一個字符,而不是一個整個一行(雖然 pexpect 設置了 re.DOTALL,會匹配一個新行。 child.expect ('.*'); 每次匹配都會成功,但是總是沒有字符返回,因為 '*' 表明前面的字符可以出現 0 次 , 在 pexpect 中,一般來說,任何 '*' 都會盡量少的匹配。
isalive() 的使用 tips
isalive(self)
測試子程序是否還在運行。這個方法是非阻塞的,如果子程序被終止了,那么該方法會去讀取子程序的 exitstatus 或 signalstatus 這兩個域。返回 True 表明子程序好像是在運行,返回 False 表示不再運行。當平臺是 Solaris 時,可能需要幾秒鐘才能得到正確的狀態。 當子程序退出后立馬執行 isalive() 有時可能會返回 1 (True),這是一個 race condition,原因是子程序已經關閉了其文件描述符,但是在 isalive() 執行前還沒有完全的退出。增加一個小小的延時會對 isalive() 的結果有效性有幫助。
清單 17. isalive() 的例子代碼
delaybeforesend 的使用 tips
spawn 類的域 delaybeforesend 可以幫助克服一些古怪的行為。比如,經典的是,當一個用戶使用 expect() 期待 "Password:" 提示符時,如果匹配,立馬 sendline() 發送密碼給子程序,但是這個用戶會看到他們的密碼被 echo back 回顯回來了。這是因為,通常許多應用程序都會在打印出 "Password:" 提示符后,立馬關掉 stdin 的 echo,但是如果你發送密碼過快,在程序關掉 stdin 的 echo 之前就發送密碼出去了,那么該密碼就會被 echo 出來。
清單 18. delaybeforesend 的例子代碼
相關主題
訪問?Expect?的主頁,了解更多 Expect 的內容。
訪問 Python?官方網頁,了解更多 Python 相關知識。
有關正則表達式方面相關知識,請訪問正則表達式。
更多 SSH 相關知識,請訪問?SSH。
更多 os.system() 的介紹,請訪問?os.system()。
在 developerWorks 上查閱所有?Linux 技巧?和?Linux 教程。
參考帖子
總結
以上是生活随笔為你收集整理的python pp模块_Python模块--Pexpect的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 苏炳添代言!小米12海报曝光:发布会定档
- 下一篇: pythonlive2d_Unity-L