Hướng dẫn dùng expected java python

  1. Trang Chủ
  2. Python

Giới thiệu nền

Expect Chương trình chủ yếu được sử dụng để mô phỏng đối thoại con người, là loại câu hỏi hệ thống. Mọi người trả lời yes/no hoặc tên người dùng và mật khẩu nhập thông tin đăng nhập tài khoản. Bởi vì tình huống này đặc biệt và cồng kềnh, nhiều ngôn ngữ có nhiều nhận thức khác nhau. Lần đầu tiên Expect đã đạt được ngôn ngữ TCL, do đó Expect sau đây đề cập đến việc sử dụng và quy trình ban đầu. Quy trình chung bao gồm:

Thời gian chạy

Chương trình đòi hỏi sự phán xét và đầu vào của mọi người

Expect Kết hợp thông qua các từ khóa

Gửi một chuỗi đáp ứng chương trình theo từ khóa đến chương trình

TCL Chức năng Expect của việc thực hiện ngôn ngữ rất mạnh. Tôi đã sử dụng nó để triển khai một nền tảng thử nghiệm hoàn chỉnh cho thiết bị tường lửa. Bởi vì nó được sử dụng thuận tiện và được sử dụng rộng rãi, hầu như tất cả ngôn ngữ tập lệnh đều đạt được nhiều chức năng tương tự tương tự như Expect. Mặc dù chúng khác nhau, nhưng các nguyên tắc không khác nhau nhiều.

pexpect là việc triển khai Expect Ngôn ngữ Python. Theo quan điểm của tôi, vẫn còn một số lỗ hổng trong việc thực hiện ngôn ngữ TCL về chức năng. Ví dụ, không có sự cố buffer_full, chẳng hạn như không Đủ để thực hiện các ứng dụng chung. Đó là.

Quá trình sử dụng cơ bản

Việc sử dụng pexpect về mặt sử dụng, nó là vận hành xung quanh 3 lệnh chính:

Lần đầu tiên sử dụng spawn để thực hiện chương trình

Sau đó sử dụng expect để chờ từ khóa được chỉ định. Từ khóa này được in ra đầu ra tiêu chuẩn ở trên

Cuối cùng, khi tìm thấy từ khóa này, hãy sử dụng phương thức send để gửi chuỗi đến chương trình này theo từ khóa

Bước đầu tiên chỉ cần một lần, nhưng trong chương trình, nó sẽ tiếp tục đạp xe thứ hai, để hoàn thành toàn bộ công việc từng bước trong ba bước. Sau khi thành thạo khái niệm này, việc sử dụng pexpect rất dễ dàng. Tất nhiên pexpect sẽ không chỉ có ba phương pháp này. Trên thực tế, có nhiều phương pháp ngoại vi khác.

API

spawn [] -Express

Phương thức spawn [] được sử dụng để thực hiện một chương trình trả về xử lý hoạt động của chương trình này. Trong tương lai

process = pexpect.spawn['ftp sw-tftp']

Chuỗi ở trên spawn [] ở trên là chương trình được thực thi. Ở đây chúng tôi mở kết nối ftp với máy chủ sw-tftp. Phần tử đầu tiên trong spawn [] là lệnh được thực thi. Ngoài ra, bạn có thể chỉ định một số tham số khác, chẳng hạn như: pexpect.spawn['ftp sw-tftp', timeout=60] để chỉ định thời gian chờ thời gian. Các chi tiết này sẽ được giải thích sau.

process là tay cầm hoạt động của spawn []. Sau đó, tất cả các hoạt động của chương trình này đều dựa trên tay cầm này, do đó, nó có thể là phần quan trọng nhất. Cố gắng đặt cho nó một tên ngắn, nếu không các thủ tục sẽ có nhiều từ hơn sau. -

Lưu ý: spawn [] hoặc pexpect sẽ không dịch bất kỳ ký tự đặc biệt nào như | * ký tự trong shell , Rõ ràng chỉ có 5 ký tự [bao gồm cả khoảng trắng], nhưng theo mặc định, bất cứ khi nào expect nhận được một ký tự mới, bạn có thể khớp các ký tự này từ đầu. Thời gian, bạn có thể đặt searchwindowsize=10, do đó expect sẽ chỉ khớp các từ khóa từ ký tự [cuối cùng] mới nhất. Nếu cài đặt được đặt nếu giá trị phù hợp hơn, nó sẽ cải thiện đáng kể hiệu suất. Đừng lo lắng về việc liệu các ký tự trong bộ đệm sẽ bị loại bỏ. Cho dù đầu ra có bao nhiêu hay không, miễn là nó không theo thời gian, tất cả các ký tự sẽ luôn thu được. Cài đặt của tham số này chỉ ảnh hưởng đến hành vi phù hợp.

Tham số này thường được đặt trong lệnh expect []. Phiên bản pexpect 2.x dường như có bug và các cài đặt trong spawn không hiệu quả.

logfile - Chạy điều khiển đầu ra

Giá trị mặc định: None

Khi một tay cầm tệp được chỉ định cho tham số logfile, tất cả nội dung thu được từ đầu vào tiêu chuẩn và đầu ra tiêu chuẩn sẽ được ghi vào tệp này [lưu ý rằng chữ viết này là copy[process.send] Để làm mới tệp này [flush].

Đây là một kỹ thuật rất quan trọng: Nếu bạn muốn xem đầu ra trong quá trình spawn, bạn có thể viết các đầu ra này vào sys.stdout, ví dụ ::

process = pexpect.spawn["ftp sw-tftp", logfile=sys.stdout]

Theo cách này, bạn có thể thấy đầu vào và đầu ra trong quá trình thực hiện toàn bộ chương trình, rất phù hợp để gỡ lỗi.

Có một ví dụ khác:

process = pexpect.spawn["ftp sw-tftp"]
logFileId = open["logfile.txt", 'w']
process.logfile = logFileId

Lưu ý: Trong tệp logfile.txt, nó chứa cả đầu ra của chương trình và nội dung được gửi bởi spawn cho chương trình. Đôi khi bạn có thể không muốn điều này, vì một số nội dung xuất hiện hai lần, sau đó có hai Quan trọng logfile Các tham số liên kết:

logfile_read - Nhận nội dung của đầu ra tiêu chuẩn

Giá trị mặc định: None

Ghi lại tất cả nội dung được trả về trong chương trình thực thi, nghĩa là xóa lệnh bạn đã gửi và chỉ bao gồm phần của kết quả lệnh:

process.logfile_read = sys.stdout

Tuyên bố trên sẽ in tất cả các đầu ra trong quá trình thực hiện chương trình trên màn hình, nhưng nhìn chung không bao gồm các lệnh bạn gửi đến chương trình, nhưng hầu hết các chương trình đều có cơ chế phục hồi. Ví dụ, khi lệnh được cấp cho bạn Cũng sẽ hiển thị chuỗi trên thiết bị đầu cuối của bạn để cho bạn hiểu ký tự nào là đầu vào. Vào thời điểm này, nó sẽ được đọc bằng phương pháp này. Chỉ những trường hợp sẽ không được tiết lộ logfile_read sẽ không khả dụng, chẳng hạn như khi nhập mật khẩu.

logfile_send - Nhận nội dung của việc gửi

Giá trị mặc định: None

Ghi lại mọi thứ được gửi đến chương trình thực hiện

process.logfile_send = sys.stdout

Câu trên chỉ được in trên màn hình cho nội dung được gửi đến chương trình.

cwd - Chỉ định thư mục thực thi lệnh

Giá trị mặc định: None hoặc nói ./

cwd Các lệnh được sử dụng để chỉ định lệnh được thực thi theo đường dẫn được thực thi. Nó thường được sử dụng trong các lệnh send [], chẳng hạn như trong Linux, bạn muốn ở trong/ etc Thư mục thực thi lệnh ls - l, vì vậy bạn không cần sử dụng sendline["ls - l", cwd="/etc"].

env - Chỉ định các biến môi trường

Giá trị mặc định: None

Chỉ định giá trị của biến môi trường, giá trị này là từ điển. Nếu bạn gửi lệnh bạn gửi để sử dụng một số biến môi trường, bạn có thể cung cấp nó ở đây

ignore_sighup - Cho dù SIGHUP Tín hiệu

Giá trị mặc định: True

Tham số này được giới thiệu bởi pexpect 3.1. Trước 3.1 [chẳng hạn như pexpect 2.3], spawn Đặt ignore_sighup = False, bạn có thể thay đổi hành vi này.

delaybeforesend - Nhân vật gửi độ trễ

Giá trị mặc định: 0,05

Đây là một tham số ẩn được sử dụng để đặt độ trễ trước khi gửi chuỗi. Lý do lớn nhất để tăng tham số này là vì nhiều người gặp vấn đề như vậy:

Khi đăng nhập vào chương trình FTP, nó sẽ được hiển thị trực tiếp khi nhập mật khẩu bằng tập lệnh. Điều này dựa trên một thực tế đáng kinh ngạc là những người bình thường: khi FTP đăng nhập, trên thực tế, máy chủ sẽ in lời nhắc yêu cầu bạn nhập mật khẩu và sau đó gửi tín hiệu để hủy chức năng hiển thị trở lại. Hành động này Độ trễ tương đối cao, do đó không thể thấy mật khẩu của màn hình quay lại, nhưng tập lệnh sẽ được gửi ngay lập tức khi tìm thấy mật khẩu đầu vào, vì vậy mật khẩu sẽ xuất hiện trước khi đóng màn hình. Pexpect Để giải quyết vấn đề này, hãy đợi mặc định 50 mili giây trước khi gửi ký tự. Nếu bạn nghĩ rằng không cần thiết, bạn có thể tự đặt nó để hủy hành vi này.

expect [] -Từ khóa khớp với từ khóa

Khi spawn [] bắt đầu một chương trình và trả về chương trình để kiểm soát tay cầm, bạn có thể sử dụng phương thức expect [] để chờ từ khóa được chỉ định. Cuối cùng nó sẽ trả về 0 để biểu diễn các từ khóa cần thiết. Nếu các từ khóa khớp tiếp theo là một danh sách, một số sẽ trả về một số để chỉ ra một số từ khóa trong danh sách, bắt đầu từ 0.

expect [] sử dụng các biểu thức chính quy để phù hợp với các từ khóa cần thiết. .

Cách sử dụng:

# pattern_list Danh sách biểu thức chính quy, cho biết phù hợp với các nội dung này
# timeout Không cài đặt hoặc cài đặt thành -1, thời gian chờ sử dụng giá trị của self.timeout và mặc định là 30 giây. Bạn cũng có thể tự đặt nó.
# searchwindowsize Hàm giống như spawn, nhưng! Hãy chú ý đến điều này nhưng! Mô tả thực tế dưới đây
process.expect[pattern_list, timeout=-1, searchwindowsize=None]

searchwindowsize Ở đây thực sự hiệu quả trong phương thức expect []. Theo mặc định, None, nghĩa là mỗi ký tự được lấy từ quy trình con. Nếu có nhiều đầu ra ... ... Hiệu suất sẽ rất thấp. Nếu nó được đặt thành các giá trị khác, điều đó có nghĩa là có bao nhiêu ký tự được đọc từ quá trình con để tạo ra một kết quả phù hợp, điều này sẽ làm giảm đáng kể số lượng hiệu suất phù hợp và tăng hiệu suất.

Sau khi thử nghiệm, đối với một quy trình phụ với 48100.000 ký tự, khi cài đặt searchwindowsize đến 2000, phải mất 73,2730 giây để hoàn thành quá trình xử lý hoàn chỉnh; Quá trình con giống nhau đặt tham số này thành None> 1949.6259 giây, Oh, my Lady GAGA... ... Đó là chỉ số tăng.

Trận đấu đơn giản nhất

process.expect['[Nn]ame']

Mã trên đại diện cho: Phương pháp khớp "]
process.send["by\n"]

Phương thức này sẽ trả về số lượng ký tự để gửi ký tự.

sendline [] -steent

Sự khác biệt duy nhất giữa sendline [] và send [] là thêm một biểu tượng đi xe -để vượt qua chuỗi gửi, cũng sử dụng chúng ở những nơi khác nhau:

Chỉ cần gửi ký tự, sử dụng send []

Nếu bạn cần quay lại sau khi gửi ký tự, hãy sử dụng sendline []

Nó cũng trả về số lượng ký tự được gửi

sendcontrol [] -Send Tín hiệu điều khiển

sendcontrol [] Gửi các ký tự điều khiển đến chương trình con, chẳng hạn như ctrl+C hoặc

process.match - Được bảo tồn một thể hiện của biểu thức thông thường phù hợp, so với after ở trên, một là một chuỗi phù hợp, một là một thể hiện biểu thức chính quy phù hợp

Nếu expect [] là sai, thì before được lưu trữ trong tất cả dữ liệu trong bộ đệm vị trí hiện tại, after và match là None

self.exitstatus | self.signalstatus

Hai giá trị ở trên được sử dụng để lưu trạng thái thoát của chương trình con spawn, nhưng lưu ý rằng chỉ có hai tham số này sẽ được đặt sau khi sử dụng lệnh process.close [].

hướng dẫn khác

CR/LF Thỏa thuận

Người ta biết rằng có nhiều loại lợi nhuận để thay thế dòng trên thế giới, điều này khiến chúng ta gặp nhiều rắc rối, chẳng hạn như ::

windows Sử dụng \ r\n để cho biết sự trở lại của xe

Linux like Trong hệ thống, sử dụng \ r để chỉ ra chiếc xe nhập

Mac Trong hệ thống, sử dụng \ n để chỉ ra chiếc xe trở lại cho xe hơi

Những loại xe buýt này đã gây ra những khó khăn lớn trong cấy ghép mã. Hầu như tất cả các ngôn ngữ lập trình được hỗ trợ bởi toàn bộ nền tảng đều có giải pháp riêng và giải pháp của pexpect là ::

Bất kể nền tảng nào, hãy nhập ngân hàng để thay thế nó bằng \ r\n

Do đó, nếu chúng ta muốn khớp với biểu tượng trả về trong expect, chúng ta phải làm điều này:

process.expect['\r\n']

# Từ cuối cùng trong dòng:
process.expect['\w+\r\n']

# Phương thức khớp bên dưới là sai [trong ngôn ngữ kịch bản khác là chính xác, chẳng hạn như thực hiện ngôn ngữ Expect
process.expect['\r']

$ * + Thỏa thuận

Trong biểu thức chính quy, biểu tượng $ đại diện cho trận đấu cuối cùng từ dòng-nhưng nó không hợp lệ trong pexpect. Nếu bạn muốn khớp với phần cuối của dòng, thì phải có một dòng dữ liệu, nghĩa là có một biểu tượng thay đổi -car -car, nhưng việc xử lý pexpect không được thực hiện theo dòng. Dữ liệu.

Vì vậy, bất kể thời gian nào, đừng khớp với biểu tượng $ trong expect [].

Bởi vì pexpect Chỉ chỉ xử lý một ký tự tại một thời điểm, chức năng thêm số [+], số sao [*] cũng không hợp lệ, ví dụ:

# Bất cứ khi nào bạn, bạn sẽ chỉ trả về một ký tự
process.expect[".+"]

# Bất cứ khi nào bạn bất cứ lúc nào, bạn sẽ chỉ quay lại nhân vật trống
process.expect[".*"]

Gỡ lỗi chương trình

Nếu bạn muốn gỡ lỗi pexpect, bạn có thể sử dụng phương pháp sau:

str[processHandle]

#At pexpect.spawn [] để tạo một quy trình và kiểm soát chương trình thông qua xử lý quá trình này.
# Nhưng nếu tay cầm này được tải lại với hàm str []? Nó cho thấy một loạt thông tin nội bộ của xử lý điều khiển này, chẳng hạn như ::
process = pexpect.spawn["ftp sw-tftp"]
print str[process]
#
version: 2.3 [$Revision: 399 $]
command: /usr/bin/ftp
args: ['/usr/bin/ftp', 'sw-tftp']
searcher: searcher_re:
0: EOF
buffer [last 100 chars]:
before [last 100 chars]: was 14494 bytes in 1 transfers.
221-Thank you for using the FTP service on sw-tftp.
221 Goodbye.

after:
match:
match_index: 0
exitstatus: 0
flag_eof: True
pid: 50733
child_fd: 3
closed: False
timeout: 30
delimiter:
logfile: None
logfile_read: None
logfile_send: None
maxread: 2000
ignorecase: False
searchwindowsize: None
delaybeforesend: 0.05
delayafterclose: 0.1
delayafterterminate: 0.1

Mẹo và bẫy

Khớp chu kỳ

Mô -đun pexpect của Python được so sánh với TCL expect, rõ ràng là không đủ, bao gồm cả khớp. Mô -đun expect của TCL có thể cung cấp một loạt các từ khóa phù hợp, sau đó đảm bảo cùng một câu lệnh expect của câu lệnh continue.

Ví dụ: expect có 3 từ khóa, sẽ đáp ứng câu lệnh continue khi nó được khớp với từ khóa thứ hai. Ví dụ, thời gian chờ được đặt thành 10 giây và sau đó lặp lại 3 lần để thực sự làm thêm.

Thật không may, Python pexpect không có chức năng như vậy. Nhưng nếu bạn muốn mô phỏng tình huống này, không phải là không thể. Bạn có thể hoàn thành nó thông qua câu lệnh while, chẳng hạn như:

while True:
index = process.expect[[
pexpect.TIMEOUT,
pexpect.EOF,
]}
if index == 0:
print "time is out"
# Re -match
continue
elif index == 1:
print "Terminate."
#Vòng lặp
break

Chiến lược có được nội dung của before và trống buffer

Trong hầu hết các trường hợp, chúng tôi sẽ sử dụng các biến before để có được kết quả thực thi lệnh. Nhưng bạn có thực sự biết cách sử dụng before?

Khi nào before lưu những gì bạn cần? Chi tiết này phải rất rõ ràng. Hãy lấy lệnh làm ví dụ làm ví dụ:

Ở đây chúng tôi dự kiến ​​sẽ nằm trong hệ thống linux. Chúng tôi mong đợi các bước như vậy:

Khớp với lời nhắc, để hệ thống sẵn sàng chấp nhận lệnh

Gửi lệnh

Kết quả thực thi lệnh

handle.expect[prompt]
handle.sendline["ls –l"]
handle.expect[prompt]
output = handle.before

Tổng cộng có 4 câu, bạn có thể nhận được kết quả của lệnh ls - l, nhưng chậm, bạn có tìm thấy bất kỳ địa điểm không hợp lý nào không?

Các câu thứ nhất và thứ hai là các lời nhắc hệ thống phù hợp và các lệnh gửi, tương đối bình thường.

Nhưng tại sao câu thứ ba lại khớp với lời nhắc hệ thống? Theo trí tưởng tượng chung, sau khi gửi lệnh, thiết bị sẽ thực thi và trả về kết quả, để bạn có thể sử dụng câu lệnh handle.before để có được các nội dung này?

Trên thực tế, từ before có thể hiểu rằng nó không có hiệu lực trong thời gian thực. Nội dung trong đó thực sự là lần cuối expect khớp, hãy xóa từ khóa phù hợp, bộ đệm hệ thống tất cả các nội dung còn lại . Nói cách khác, nếu câu thứ ba là output = handle.before, thì nội dung trong đó là expect trong câu đầu tiên xóa nội dung prompt để lại trong bộ đệm. Rõ ràng, nó sẽ không bao gồm nội dung của lệnh ls - l phía sau.

Vì vậy, nếu bạn muốn nhận ls - l, cách duy nhất là thêm một từ khóa expect khác. Đây là một điểm rất quan trọng.

Ngoài ra, buffer trong pexpect là một chìa khóa, nhưng nó không thể được vận hành trực tiếp. before/after có nguồn gốc trực tiếp từ nó và kết hợp từ khóa của expect cũng được khớp trong buffer.

Vì tầm quan trọng của nó, nội dung trong biến này cần phải cảnh giác đặc biệt. Ví dụ: khi chúng tôi sẽ đăng nhập vào thiết bị, gửi lệnh và ba bước thoát, thiết bị được viết thành 3 chức năng, tốt nhất là đảm bảo rằng mỗi bước sẽ không ảnh hưởng đến bước tiếp theo. Vận hành:

handle.buffer = ""

Mã thể hiện mã

FTP Đăng nhập máy chủ

Mã sau tương đối đơn giản, nghĩa là đăng nhập vào máy chủ FTP và tự động nhập mật khẩu. Sau khi nhập máy chủ, nhập một vài lệnh được xác định trước, sau đó trả về điều khiển qua điều khiển. rằng thao tác của bạn đã hoàn tất và tập lệnh sẽ tự động thoát ftp Đăng nhập.

#!/usr/bin/env python

import sys
import pexpect

# FTP Mẹo tiêu chuẩn của máy chủ
ftpPrompt = 'ftp>'

# FTP máy chủ và đặt đầu ra trong quá trình hoạt động vào đầu ra tiêu chuẩn
process = pexpect.spawn['ftp sw-tftp']
process.logfile_read = sys.stdout

# Quy trình đăng nhập máy chủ
process.expect['[Nn]ame']
process.sendline['dev']
process.expect['[Pp]assword']
process.sendline['abcd1234']

# Tự động nhập một số lệnh được xác định trước
cmdList = ["passive", 'hash']

for cmd in cmdList:
process.expect[ftpPrompt]
process.sendline[cmd]

process.expect[ftpPrompt]

# Tại đây, tôi sẽ trả lại điều khiển FTP cho người dùng. Sau khi hoàn thành đầu vào của người dùng
# ctrl+] Thu hồi điều khiển quyền đối với tập lệnh là giá trị mặc định và người dùng cũng có thể đặt các giá trị khác, chẳng hạn như '\ x2a'
# Khi người dùng nhấn số ngôi sao, hãy trả lại. Giá trị này thực sự là một mã thập lục phân của ASCII. Mối quan hệ tương ứng của chúng
# Bạn có thể đến những nơi khác để tự tìm thấy nó, nhưng bạn phải là thập lục phân và tiền tố là \ x
process.interact[]

# Khi người dùng thanh toán điều khiển ngay cho tập lệnh, thì tập lệnh thoát ra khỏi máy chủ ftp
# Lưu ý lệnh trống sendline [] bên dưới, nó rất quan trọng. Khi người dùng thanh toán cho điều khiển ngay cho tập lệnh,
Bộ đệm # script không có trong bộ đệm, vì vậy không thể khớp được. Ở đây, một chiếc xe nhập sẽ lấy nó từ máy chủ
# Một số nội dung, để bạn có thể khớp nó.
# EOF cuối cùng là một phương thức để xác nhận việc hoàn thành kết nối FTP.
process.sendline[]
process.expect[ftpPrompt]
process.sendline['by']
process.expect[pexpect.EOF]

Tập lệnh trên thực sự thiếu rất nhiều lỗi, chẳng hạn như lỗi tên người dùng hoặc lỗi mật khẩu sau khi đăng nhập hoặc không thể kết nối với máy chủ, nhưng hành động cốt lõi đã hoàn tất.


Django Sử Dụng XLWT Xuất

Nghiên cứu của bài viết này chủ yếu để ghi lại phương pháp xuất khẩu, và không có REST xử lý và xử lý bất thường. Duy tr

Chủ Đề