程式扎記: [ FLib ] JExpect : Python Pexpect 的 Java 版本 (1)

標籤

2015年2月9日 星期一

[ FLib ] JExpect : Python Pexpect 的 Java 版本 (1)

Preface 
Python 的 Pexpect 模組 提供使用者能夠與互動的程式進行溝通: 
Pexpect is a pure Python module for spawning child applications; controlling them; and responding to expected patterns in their output. Pexpect works like Don Libes’ Expect. Pexpect allows your script to spawn a child application and control it as if a human were typing commands.

而這裡的 JExpect 可以想像成Pexpect 模組 的 Java 版本, 並封裝到 Flib.jar 模組. 底下將針對該類別的使用進行介紹. 

Usage Of JExpect 
JExpect 上提供靜態方法 Spawn(String cmd) 讓你可以透過 Spawn 一個新的 Process 來執行給定命令: 
  1. /** 
  2. * BD: Spawn a Process by executing given command. 
  3.  
  4. * @param cmd: Command to execute in Spawn process. 
  5. * @return 
  6. * @throws Exception 
  7. */  
  8. public static ISpawnProcess Spawn(String cmd) throws Exception  
假設我們有一個互動的程式 HelloShell.jar (download), 使用如下: 
$ java -jar HelloShell.jar
This is Hello Shell:
> name
My name is John
> age
My age is 35
> test
Sorry, unknown workd='test'!
> bye
Nice to meet you!
Bye!
 # 返回 Bash Shell interactive

則你可以使用下面代碼啟動此互動程式, 並使用返回的 ISpawnProcess 介面的實作物件進行與程式互動: 
  1. ISpawnProcess sp = JExpect.Spawn("java -jar HelloShell.jar")  
接著你可以使用ISpawnProcess 介面上的方法將輸入送到 Stdin 中 (模擬從鍵盤輸入): 
  1. /** 
  2. * Send input line to System.in. 
  3.  
  4. * @param line: Line to be sent to System.in 
  5. * @throws Exception 
  6. */  
  7. public void sendLine(String line) throws Exception;  
或是透過下面 API 對 Stdout/Stderr 進行 Pattern 比對: 
  1. public Future expect_asyn(String pattern) throws Exception;  
  2. public boolean expect_async(String pattern, int timeout) throws Exception;  
  3. public boolean expect(String pattern, int timeout) throws Exception;  
  4. public boolean expect(String pattern) throws Exception;  
  5. public boolean expect_exact(String pattern, int timeout) throws Exception;  
  6. public boolean expect_exact(String pattern) throws Exception;  
譬如你可以在進入 Interactive 前針對 Hello Shell 在 Stdout 上輸出的 "This is Hello Shell" 中的 "Hello Shell" 字串來判斷目前已經成功進入互動模式, 範例代碼如下: 
  1. ISpawnProcess sp = JExpect.Spawn("java -jar HelloShell.jar")    
  2. if(sp.expect_async("Hello Shell"2000))  
  3. {  
  4.     printf("\t[Info] Entering Interactive console...\n")  
  5. }    
  6. else  
  7. {  
  8.     printf("\t[Error] Fail to open Interactive console!\n")  
  9.     sp.close()  // Close Spawn Process  
  10. }  
接著你便可以透過 sendLine(String msg) 傳送命令到 Stdin 與程式互動, 並從 lastExpect 取出比對到預期 String pattern 中所有 Stdout 輸出的內容: 
  1. sp.sendLine("name")  
  2. printf("\t[Info] Expect Name...\n")  
  3. sp.expect("My name is"2000)  
  4. printf("\t${sp.lastExpect[-1]}\n")  
底下為完整的 Groovy 範例代碼與此互動程式進行互動: 
  1. import flib.util.system.ISpawnProcess  
  2. import flib.util.system.JExpect  
  3.   
  4. printf("\t[Info] Enter Interactive App...\n")  
  5. ISpawnProcess sp = JExpect.Spawn("java -jar HelloShell.jar")  
  6.   
  7. printf("\t[Info] Expect Interactive...\n")  
  8. sp.expect_async("Hello Shell"2000)  
  9.   
  10. sp.sendLine("name")  
  11. printf("\t[Info] Expect Name...\n")  
  12. sp.expect_async("My name is"2000)  
  13. printf("\t${sp.lastExpect[-1]}\n")  
  14.   
  15. sp.sendLine("age")  
  16. printf("\t[Info] Expect Age...\n")  
  17. sp.expect_async("My age is"2000)  
  18. printf("\t${sp.lastExpect[-1]}\n")  
  19.   
  20. sp.sendLine("test")  
  21. printf("\t[Info] Expect Error...\n")  
  22. sp.expect_async("unknown"2000)  
  23. printf("\t${sp.lastExpect[-1]}\n")  
  24.   
  25. sp.sendLine("bye")  
  26. printf("\t[Info] Expect Bye...\n")  
  27. sp.expect_async("Bye"2000)  
  28. printf("\t${sp.lastExpect[-1]}\n")  
  29.   
  30.   
  31. printf("\t[Info] Done...\n")  
  32. sp.close()  
  33. printf("\t[Info] Exit main...\n")  
執行結果如下: 
$ groovy -cp "../glibs/*:Flib.jar" HelloShellTest.groovy # JExpect 封裝於 Flib.jar 
[Info] Change password of user='test'...
[Info] Expect Interactive...
[Info] Expect Name...
> My name is John
[Info] Expect Age...
> My age is 35
[Info] Expect Error...
> Sorry, unknown workd='test'!
[Info] Expect Bye...
Bye!
[Info] Done...
[Info] Exit main...

Supplement 
Flib - frequent-used-functionality 
[ Python 文章收集 ] python Pexpect

沒有留言:

張貼留言

網誌存檔

關於我自己

我的相片
Where there is a will, there is a way!