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 <+ Muốn sử dụng đúng nghĩa của các ký hiệu này trong hệ thống linux, bạn phải thêm shell Để chạy, đây là một sai lầm dễ mắc phải.

Đúng cách:

process = pexpect.spawn('/bin/bash –c "ls –l | grep LOG > log_list.txt"')
process.expect(pexpect.EOF)

spawn () Một phương thức cuộc gọi khác là tham số đầu tiên là chương trình chính và tham số tiếp theo là tham số của chương trình chính. Có phải là rắc rối để hiểu không? Nhìn vào mã thực tế:

cmd = "ls –l | grep LOG > log_list.txt"
process = pexpect.spawn("/bin/bash", ["-c", cmd])
process.expect(pexpect.EOF)

Những mã này giống như ví dụ trên, nó có rõ ràng hơn không?

spawn Các tùy chọn bao gồm các tùy chọn sau:

timeout - Thời gian chờ thời gian

Giá trị mặc định: 30 (đơn vị: thứ hai)

Chỉ định thời gian chờ mặc định của chương trình. Sau khi chương trình được bắt đầu, sẽ có đầu ra và chúng tôi cũng sẽ kiểm tra xem các từ khóa trong đầu ra có được biết và xử lý trong tập lệnh hay không. Nếu chương trình không được tìm thấy trong thời gian quy định, nó sẽ sai.

maxread - Cài đặt bộ nhớ cache

Giá trị mặc định: 2000 (đơn vị: ký tự)

Chỉ định số lượng dữ liệu được đọc từ đầu ra lệnh cùng một lúc. Nếu bộ số tương đối lớn, thì số lượng dữ liệu được đọc từ TTY sẽ ít hơn.

Đặt thành 1 có nghĩa là đóng bộ đệm đọc.

Đặt giá trị lớn hơn sẽ cải thiện hiệu suất của việc đọc nhiều dữ liệu, nhưng nó sẽ lãng phí nhiều bộ nhớ hơn. Cài đặt của giá trị này sẽ cung cấp nhiều chức năng hơn với searchwindowsize.

Kích thước của bộ đệm không ảnh hưởng đến nội dung thu được, điều đó có nghĩa là nếu một lệnh xuất ra hơn 2000 ký tự, các ký tự bộ đệm trước đó sẽ không mất nó, nhưng nó sẽ được đặt ở những nơi khác. self ví dụ spawn) Vẫn có thể nhận được đầu ra đầy đủ.

searchwindowsize - Chế độ phù hợp với ngưỡng

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

Tham số searchwindowsize được sử dụng với sự hợp tác với tham số maxread. Chức năng của nó tinh tế hơn, nhưng nó có thể giảm đáng kể thời gian phù hợp khi có nhiều ký tự trong bộ đệm.

Theo mặc định, expect () khớp với các từ khóa được chỉ định là như thế này: mỗi lần bạn nhận được một ký tự trong bộ đệm, bạn sẽ khớp với tất cả các biểu thức thông thường của toàn bộ bộ đệm. Bạn có thể tưởng tượng rằng nếu chương trình trả về đặc biệt đặc biệt là Nhiều lần, hiệu suất thấp sẽ như thế nào.

Giá trị của cài đặt searchwindowsize cho biết số lượng nhận được bao nhiêu ký tự cùng một lúc trước khi khớp biểu thức. Ví dụ, có một số lượng lớn đầu ra hiện tại, nhưng từ khóa phù hợp là tiêu chuẩn FTP nhắc ftp >, 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

Khi các từ khóa trên khớp, nó sẽ trả lại 0 cho khớp, nhưng nếu nó không được khớp? Mặc định là chờ đợi, nhưng nếu timeout được đặt, nó sẽ mất hết thời gian chờ.

Kết hợp một loạt đầu ra

Trên thực tế, expect () có thể khớp với một loạt các đầu ra. Bằng cách kiểm tra đầu ra phù hợp, chúng ta có thể làm những việc khác nhau. Ví dụ: kết nối ftp của spawn trước. Nếu chúng ta có các tình huống khác nhau sau khi nhập tên người dùng, chúng ta có thể thực hiện các chuyển động khác nhau bằng cách theo dõi các tình huống khác nhau này, chẳng hạn như ::

index = process.expect([
'Permission Denied',
'Terminal type',
'ftp>',
])
if index == 0:
print "Permission denied at host, can't login."
process.kill(0)
elif index == 1:
print "Login ok, set up terminal type…"
process.sendline('vty100')
process.expect("ftp>")
elif index == 2:
print "Login Ok, please send your command"
process.interact()

Trong mã trên, phương thức expect là một danh sách. Mỗi phần tử trong danh sách là một biểu thức thông thường của từ khóa, có nghĩa là chúng tôi mong chờ ba tình huống này và expect Trả về để trả về một giá trị đơn hàng đại diện cho yếu tố tôi phù hợp (nghĩa là, loại tình huống nào đã xảy ra). Giá trị đơn hàng này được tính từ 0.

Sau expect, câu lệnh if bên dưới bắt đầu xử lý ba tình huống này:

Không đủ quyền, đây có thể là một vấn đề với máy chủ ftp hoặc không có tài khoản đó hoặc các tình huống khác. Dù sao, miễn là bạn tìm thấy điều này, chúng tôi sẽ nhắc nó cho người dùng và sau đó tiêu diệt quy trình này.

Đăng nhập thành công, nhưng người dùng chỉ định chế độ thiết bị đầu cuối thực sự sử dụng nó, vì vậy chúng tôi chỉ định chế độ vty100 trong mã, sau đó xem nó có thể thực sự được sử dụng

Nó thành công trong đăng nhập và bạn cũng có thể trực tiếp nhập thao tác lệnh ftp, vì vậy chúng tôi nhắc nhở người dùng và sau đó cung cấp cơ quan hoạt động cho người dùng

Ngoài ra còn có một trường hợp đặc biệt. Nếu hai được khớp cùng một lúc, tôi nên làm gì? Nói một cách đơn giản:

Trong luồng gốc, nội dung đầu tiên được khớp với các từ khóa sẽ được sử dụng

Trong danh sách từ khóa phù hợp, bên trái sẽ được sử dụng

Cho một ví dụ:

# Nếu nội dung trong luồng là "hello world" "
index = process.expect(["hi", "hello", "hello world"])

Giá trị trả về là 1, nghĩa là 'hello' được khớp, ngay cả khi trận đấu thực sự tốt nhất là "hello world", nhưng vì nó được đặt phía sau, nó vẫn không hợp lệ.

kỹ năng

Nếu bạn muốn kiểm tra hoặc khớp expect.EOF và expect.TIMEOUT, bạn phải đưa chúng vào danh sách phù hợp để chúng có thể được xử lý bằng cách kiểm tra các số được trả về. Nếu bạn không đưa nó vào danh sách, lỗi EOF hoặc TIMEOUT sẽ xảy ra và chương trình sẽ dừng nửa chừng.

Có một số ngữ pháp đặc biệt trong các quy tắc phù hợp, chẳng hạn như hai quy tắc đầu tiên trong các quy tắc sau không liên quan đến vụ án. Điều quan trọng là thế này (?? i) Các quy tắc phù hợp, tương đương với từ khóa của re.IGNORE hoặc re.I, bởi vì nó không phải là một công cụ biểu thức thực sự thông thường, vì vậy pexpect sử dụng cú pháp đặc biệt này:

child.expect(['(?i)etc', '(?i)readme', pexpect.EOF, pexpect.TIMEOUT])

expect_exact () -cy khớp chính xác

Việc sử dụng nó giống như expect (). Sự khác biệt duy nhất là danh sách phù hợp của nó không còn sử dụng các biểu thức chính quy.

Về mặt hiệu suất, expect_exact () tốt hơn, bởi vì ngay cả khi bạn không sử dụng các biểu thức chính quy, bạn chỉ cần sử dụng một vài ký tự expect () để trước tiên chuyển đổi chúng thành chế độ biểu thức thông thường và sau đó tìm kiếm Một lần nữa, nhưng expect_exact () sẽ không, và nó sẽ không chuyển đổi một số ký hiệu đặc biệt.

expect_list () -phù hợp trước chuyển đổi

Phương thức sử dụng giống như expect (). Sự khác biệt duy nhất là danh sách biểu thức chính quy trong nó sẽ chỉ được chuyển đổi một lần.

expect () Một chút ngu ngốc. Mỗi cuộc gọi sẽ thay đổi biểu thức chính quy bên trong (tất nhiên có những cách khác để tránh). Hành động sẽ giảm hiệu suất. Trong trường hợp này, nên sử dụng expect_list () .

Hướng dẫn:

# timeout -1, sử dụng giá trị của self.timeout
# searchwindowsize to -1, cũng sử dụng giá trị mặc định của hệ thống
process.expect_list(pattern_list, timeout=-1, searchwindowsize=-1)

expect_loop()

Được sử dụng để có được nội dung từ đầu vào tiêu chuẩn. Từ loop có nghĩa là nó sẽ nhập một chu kỳ. Các từ khóa phải được lấy từ đầu vào tiêu chuẩn trước khi chúng tiếp tục thực hiện.

Hướng dẫn:

expect_loop(self, searcher, timeout=-1, searchwindowsize=-1)

send () -Send từ khóa

send (), là một trong ba hoạt động chính, được sử dụng để gửi một chuỗi được chỉ định đến chương trình. Nó không có vị trí đặc biệt, chẳng hạn như ::

process.expect("ftp>")
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.sendcontrol('g')

sendeof () -Send EOF tín hiệu

Gửi tín hiệu End Of File đến chương trình con.

sendintr () -send một tín hiệu chấm dứt

Gửi tín hiệu SIGINT đến chương trình con, tương đương với kill 2 trong Linux, sẽ trực tiếp chấm dứt quy trình phụ.

interact ()

interact () chỉ ra rằng các quyền điều khiển sẽ được bàn giao cho người dùng (hoặc đầu vào tiêu chuẩn). Trong các trường hợp bình thường, pexpect sẽ tiếp quản tất cả các đầu vào và đầu ra, nhưng đôi khi tôi vẫn muốn người dùng can thiệp hoặc chỉ để hoàn thành công việc, interact () rất hữu ích.

Ví dụ:

Khi đăng nhập vào máy chủ ftp, tôi hy vọng người dùng nhập mật khẩu theo cách thủ công trong giai đoạn nhập mật khẩu người dùng và sau đó tập lệnh hoàn thành công việc còn lại (không an toàn khi viết mật khẩu người dùng trong tập lệnh) )

Tôi chỉ muốn hoàn thành công việc đăng nhập, chẳng hạn như ssh để kết nối với một máy chủ xa, nhưng nó phải là một vài bước nhảy ở giữa. Thật khó khăn khi sử dụng đầu vào thủ công. Do đó cũng làm điều đó cho người dùng.

Hướng dẫn:

# escape_character là khi người dùng xuất, các ký tự được chỉ định ở đây, điều đó có nghĩa là hoạt động của bạn đã hoàn thành và điều khiển được sử dụng lại thành pexpect
process.interact(escape_character='\x1d', input_filter=None, output_filter= None)

Để biết chi tiết, phương thức này sẽ kiểm soát điều khiển cho người dùng (hoặc bàn phím do người dùng vận hành), sau đó chỉ cần xuất ra đầu ra tiêu chuẩn, đầu ra lỗi tiêu chuẩn và đầu vào tiêu chuẩn cho hệ thống.

Bằng cách đặt giá trị của escape_character, mã trả về có thể được xác định. Mặc định là ctrl+] hoặc ^]. Sau khi nhập quá trình thực hiện mã trả về.

close () -Ứng dụng dừng

Nếu bạn muốn đóng chương trình con nửa chừng, bạn có thể sử dụng close để hoàn thành nó. Sau khi gọi phương thức này, bạn sẽ trả về giá trị trả về của chương trình này.

Nếu bạn đặt force=True Để buộc chương trình này, quá trình có thể là gửi tín hiệu SIGHUP và SIGINT. Nếu nó không hợp lệ, hãy gửi tín hiệu SIGKILL Đóng.

Phương thức này được cho phép nhiều lần, nhưng nó không được đảm bảo trả lại giá trị trả về chính xác mỗi lần. Cố gắng không làm điều này. Nếu bạn muốn đảm bảo rằng chương trình được đóng, chỉ cần đặt giá trị của force.

Sau đây là ví dụ:

process.close(force=True)

terminate () -Stop Ứng dụng

Nó có thể được coi là bí danh của close () ở trên, bởi vì cả hai hàm và phương thức đều giống nhau.

Kill () -Send SIGKILL Tín hiệu

Gửi tín hiệu của SIGKILL đến chương trình con.

flush()

Không có gì không làm gì, chỉ để tương thích với phương thức tệp.

isalive () -check trạng thái hoạt động của chương trình con

Kiểm tra xem chương trình con được gọi là đang chạy. Phương thức này đang chạy dưới chế độ không chặn.

Nếu lợi nhuận là True chỉ ra rằng chương trình con đang chạy; Trở lại False cho biết chương trình bị chấm dứt.

isatty () -check xem nó có chạy trên thiết bị TTY

Trả về True có nghĩa là mở và kết nối với loại thiết bị tty hoặc trả về False để chỉ ra không được kết nối.

next () -Enovation của dòng nội dung tiếp theo

Giống như tệp hoạt động, phương thức này cũng là nội dung của dòng tiếp theo của bộ đệm.

read () -ee trở lại nội dung còn lại

Có được tất cả các nội dung được trả lại bởi chương trình con. Nói chung, chúng ta có thể sử dụng expect để mong chờ một số nội dung, và sau đó lấy nó bằng process.before, nhưng phương pháp này có tiền đề: đó là <+phải là < +Đầu tiên expect Một số ký tự nhất định, sau đó bạn có thể sử dụng process.before để có được nội dung còn lại trong bộ đệm.

Việc sử dụng read () rất khác nhau. Nó mong chờ tín hiệu EOF, sau đó trả về tất cả các đầu ra trước tín hiệu này, giống như đọc một tệp.

Trong các trường hợp bình thường, chương trình tương tác sẽ trả về EOF Khi nó được đóng, chẳng hạn như lệnh by để đóng máy chủ ftp hoặc sử dụng lệnh exit để đóng một lệnh ssh sự liên quan.

Phương pháp này tương đối hẹp, vì phương thức expect.EOF có thể được thay thế bằng expect.EOF. Tất nhiên, nếu đó là lệnh của máy này, nó sẽ trả về EOF Mỗi khi nó được thực thi. Trong trường hợp này, nó rất hữu ích:

process = pexpect.spawn('ls –l')
output = process.read()
print output

Nó trông hơi nhàm chán? Nhưng tôi nghĩ rằng phải có bất kỳ lý do để hỗ trợ phương pháp này.

Bạn có thể đặt số lượng ký tự được trả về bởi read(size=-1). Nếu nó không được đặt hoặc đặt thành số âm, số dương sẽ trả về số nội dung được chỉ định.

readline () - Quay trở lại đầu ra hàng

Trả về một dòng đầu ra, nội dung của return bao gồm ký tự \ r\n cuối cùng.

Bạn cũng có thể đặt readline(size=-1) để chỉ định số lượng ký tự được trả về. Mặc định là số âm cho biết trả về được trả về.

readlines () -Đầu ra của chế độ danh sách trả về

Trả về một danh sách, mỗi phần tử trong danh sách là một dòng (bao gồm \ r\n ký tự).

setecho) -sub -sub -program chế độ phản hồi

Đặt phương thức phản hồi của chương trình con khi chạy. Nói chung, khi gửi các ký tự đến chương trình con, các ký tự này sẽ được hiển thị trên đầu ra tiêu chuẩn, để bạn có thể thấy nội dung bạn gửi, nhưng đôi khi, chúng tôi không cần hiển thị nó sau đó có thể sử dụng phương pháp này để đặt nó.

Lưu ý rằng bạn phải đặt nó trước khi gửi ký tự và mã sau khi cài đặt đã hợp lệ. Ví dụ:

process = pexpect.spawn('cat')

# Theo mặc định, chuỗi 1234 sau sẽ được hiển thị hai lần, một khi nó được trả về bởi pexpect và lệnh kia là cat được trả về.
process.sendline("1234")

# Bây giờ chúng ta tắt hàm echo của pexpect ()
process.setecho(False)

# Các ký tự bên dưới sẽ chỉ được hiển thị một lần, được trả về bởi cat
process.sendline("abcd")

# Bây giờ lại mở lại chức năng echo, bạn có thể thấy các ký tự chúng tôi gửi lại
process.setecho(True)

setwinsize () -Kích thước của cửa sổ bảng điều khiển

Nếu chương trình con là bảng điều khiển (TTY), chẳng hạn như kết nối SSH Đặt điều khiển này quá nhiều điều khiển quá nhiều kích thước (hoặc chiều dài và chiều rộng).

Phương thức cuộc gọi của nó là process.setwinsize(r, c)

Giá trị mặc định là setwinsize(24, 80), trong đó 24 là chiều cao, đơn vị là dòng; 80 là chiều rộng, và đơn vị là ký tự.

Tại sao sử dụng nó? Hãy tưởng tượng cảnh sau:

Đôi khi bạn đăng nhập vào bảng điều khiển ssh thông qua pexpect, sau đó sử dụng interact () để trao quyền điều khiển cho người dùng và sau đó người dùng đã viết thứ tự riêng của mình trong bảng điều khiển. tương đối dài, bạn sẽ thấy rằng khi lệnh ở cạnh màn hình, nó sẽ không được chuyển tự động, nhưng quay trở lại phía trước của dòng để quay lại các ký tự phía trước; Điều này sẽ không ảnh hưởng đến hiệu ứng thực tế của lệnh, nhưng nó gây khó chịu.

Tình huống này có thể được giải quyết với setwinsize (), tìm độ dài của hỗ trợ thiết bị đầu cuối của bạn, sau đó đặt nó.

wait () -Evision chờ đợi

Cho đến khi chương trình con cuộc gọi được thực thi, chương trình dừng (hoặc chờ). Nó không đọc bất kỳ nội dung nào từ chương trình con được gọi.

waitnoecho()

Nơi mà nó sử dụng là tương đối đặc biệt. Nơi duy nhất để phù hợp là: khi hàm echo của chương trình con được đặt thành Fals.

Nó trông lạ? Trên thực tế, chức năng này dựa trên một tình huống rất đáng kinh ngạc nhưng thực sự là:

Trong chế độ dòng lệnh, nhiều nơi để nhập mật khẩu, chẳng hạn như FTP/SSH, v.v ... Mật khẩu sẽ thực sự quay lại và in nó sau khi bạn nhập nó, nhưng tại sao chúng ta không thể thấy mật khẩu chúng ta đã nhập? Điều này là do mật khẩu được đặt bởi chương trình để đặt hàm echo thành False.

Bây giờ tôi biết tại sao có một phương pháp như vậy? Ví dụ: khi kết nối ssh, làm thế nào để kiểm tra xem có nên nhập mật khẩu không? Sử dụng từ khóa password là một phương thức, nhưng có một cách khác:

# ssh kết nối
process = pexpect.spawn("ssh [email protected]")

# echo được đặt thành False, điều đó có nghĩa là sẽ không có tiết lộ cục bộ
process.waitnoecho()
process.sendline('mypassword')

Nó có thể được đặt thời gian chờ, mặc định là: waitnoecho(timeout=-1), có nghĩa là thời gian chờ của hệ thống là như nhau. Tất nhiên, bạn cũng có thể đặt các cài đặt khác khác, các số được sử dụng để biểu thị thời gian chờ.

write) -send a String

Tương tự như lệnh send (), nó sẽ không trả về số lượng ký tự được gửi.

writelines () -send một danh sách chứa chuỗi chứa chuỗi

Tương tự như lệnh write (), nhưng chỉ chấp nhận danh sách chuỗi, writelines () sẽ gửi các phần tử trong các chương trình phụ từng người một và quay trở lại xe để thay đổi dòng.

Tương tự như write (), phương thức này sẽ không trả về số lượng ký tự được gửi bằng phương thức này.

Biến đặc biệt

pexpect.EOF - khớp tín hiệu chấm dứt

EOF Các biến được sử dụng rộng rãi. Ví dụ: kiểm tra xem kết nối ssh/ftp/telnet có bị chấm dứt hay không và liệu tệp có đạt đến kết thúc hay không. pexpect Hầu hết các tập lệnh sẽ được kiểm tra ở cuối các biến EOF để xác định xem nó có bị chấm dứt và thoát bình thường hay không. Ví dụ: mã sau:

process.expect("ftp>")
process.sendline("by")
process.expect(pexpect.EOF)
print "ftp connect terminated."

pexpect.TIMEOUT - Tín hiệu thời gian chờ khớp

TIMEOUT Các biến được sử dụng để khớp với thời gian chờ. Theo mặc định, thời gian chờ của expect là 60 giây. Nếu bạn chưa tìm thấy các từ khóa được mong đợi trong hơn 60 giây, hành vi này sẽ được kích hoạt, chẳng hạn như :

# pexpect.TIMEOUT, chỉ có thể có hiệu lực khi xảy ra sự cố thời gian chờ
index = process.expect(['ftp>', pexpect.TIMEOUT],)
if index == 1:
process.interactive() ; # Sẽ trao quyền điều khiển ngay cho người dùng
elif index == 2:
print "Time is out."
process.kill(0) ; # Giết quá trình

# Vậy làm thế nào để thay đổi thời gian chờ? Trên thực tế, bạn có thể sửa đổi tham số timeout trong đối tượng spawn:
# Ví dụ bên dưới chỉ thêm một dòng, vì vậy nó đã thay đổi thời gian chờ
process.timeout = 300 ; # Lưu ý dòng này
index = process.expect(['ftp>', pexpect.TIMEOUT],)
if index == 1:
process.interactive() ; # Sẽ trao quyền điều khiển ngay cho người dùng
elif index == 2:
print "Time is out."
process.kill(0) ; # Giết quá trình

process.before/after/match - Nhận đầu ra hoạt động chương trình

Khi quá trình expect () được khớp với từ khóa (hoặc biểu thức chính quy), hệ thống sẽ tự động gán 3 biến, cụ thể là before, after và match

process.before - Lưu tất cả dữ liệu trong bộ đệm khi nó khớp với từ khóa. Nói cách khác, nếu bộ đệm được lưu trong bộ đệm 100 ký tự cuối cùng đã khớp với các từ khóa, thì before là tất cả các ký tự ngoại trừ các từ khóa phù hợp với các từ khóa

process.after - Lưu các từ khóa phù hợp, ví dụ, bạn đã sử dụng các biểu thức chính quy trong expect, sau đó tất cả các ký tự khớp với biểu thức đều ở after>

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