Hướng dẫn run bash command in python - chạy lệnh bash trong python
Để phần nào mở rộng trên các câu trả lời trước đây ở đây, có một số chi tiết thường bị bỏ qua. Show
Những chủ đề này được đề cập trong một số chi tiết hơn dưới đây. Thích # XXX AVOID THIS BUG buggy = subprocess.run('dig +short stackoverflow.com') # XXX AVOID THIS BUG TOO broken = subprocess.run(['dig', '+short', 'stackoverflow.com'], shell=True) # XXX DEFINITELY AVOID THIS pathological = subprocess.run(['dig +short stackoverflow.com'], shell=True) correct = subprocess.run(['dig', '+short', 'stackoverflow.com'], # Probably don't forget these, too check=True, text=True) # XXX Probably better avoid shell=True # but this is nominally correct fixed_but_fugly = subprocess.run('dig +short stackoverflow.com', shell=True, # Probably don't forget these, too check=True, text=True) 0 hoặc # XXX AVOID THIS BUG buggy = subprocess.run('dig +short stackoverflow.com') # XXX AVOID THIS BUG TOO broken = subprocess.run(['dig', '+short', 'stackoverflow.com'], shell=True) # XXX DEFINITELY AVOID THIS pathological = subprocess.run(['dig +short stackoverflow.com'], shell=True) correct = subprocess.run(['dig', '+short', 'stackoverflow.com'], # Probably don't forget these, too check=True, text=True) # XXX Probably better avoid shell=True # but this is nominally correct fixed_but_fugly = subprocess.run('dig +short stackoverflow.com', shell=True, # Probably don't forget these, too check=True, text=True) 1Hàm 3 là một công việc ở mức độ thấp nhưng thật khó để sử dụng chính xác và bạn kết thúc việc sao chép/dán nhiều dòng mã ... đã tồn tại thuận tiện trong thư viện tiêu chuẩn như một tập hợp các chức năng trình bao tải cấp cao hơn cho các mục đích khác nhau , được trình bày chi tiết hơn trong phần sau.Đây là một đoạn từ tài liệu:
Thật không may, sự sẵn có của các chức năng trình bao bọc này khác nhau giữa các phiên bản Python.
API cấp cao so với # XXX AVOID THIS BUG buggy = subprocess.run('dig +short stackoverflow.com') # XXX AVOID THIS BUG TOO broken = subprocess.run(['dig', '+short', 'stackoverflow.com'], shell=True) # XXX DEFINITELY AVOID THIS pathological = subprocess.run(['dig +short stackoverflow.com'], shell=True) correct = subprocess.run(['dig', '+short', 'stackoverflow.com'], # Probably don't forget these, too check=True, text=True) # XXX Probably better avoid shell=True # but this is nominally correct fixed_but_fugly = subprocess.run('dig +short stackoverflow.com', shell=True, # Probably don't forget these, too check=True, text=True) 3____10 được tái cấu trúc và mở rộng là hợp lý và linh hoạt hơn so với các chức năng di sản cũ mà nó thay thế. Nó trả về một đối tượng 6 có nhiều phương pháp khác nhau cho phép bạn truy xuất trạng thái thoát, đầu ra tiêu chuẩn và một vài kết quả và chỉ số trạng thái khác từ quy trình con đã hoàn thành. 0 là cách để đi nếu bạn chỉ cần một chương trình để chạy và trả lại quyền kiểm soát cho Python. Để biết thêm các kịch bản liên quan (các quy trình nền, có lẽ với I/O tương tác với chương trình phụ huynh Python), bạn vẫn cần sử dụng 3 và tự mình chăm sóc tất cả các hệ thống ống nước. Điều này đòi hỏi một sự hiểu biết khá phức tạp về tất cả các bộ phận chuyển động và không nên được thực hiện một cách nhẹ nhàng. Đối tượng 5 đơn giản hơn đại diện cho quá trình (có thể là vẫn còn) cần được quản lý từ mã của bạn trong phần còn lại của vòng đời của quá trình phụ.Có lẽ nên nhấn mạnh rằng chỉ 3 chỉ tạo ra một quá trình. Nếu bạn để nó ở đó, bạn có một quy trình con chạy đồng thời cùng với Python, vì vậy một quá trình "nền". Nếu nó không cần phải thực hiện đầu vào hoặc đầu ra hoặc phối hợp với bạn, nó có thể thực hiện công việc hữu ích song song với chương trình Python của bạn.Tránh # XXX AVOID THIS BUG buggy = subprocess.run('dig +short stackoverflow.com') # XXX AVOID THIS BUG TOO broken = subprocess.run(['dig', '+short', 'stackoverflow.com'], shell=True) # XXX DEFINITELY AVOID THIS pathological = subprocess.run(['dig +short stackoverflow.com'], shell=True) correct = subprocess.run(['dig', '+short', 'stackoverflow.com'], # Probably don't forget these, too check=True, text=True) # XXX Probably better avoid shell=True # but this is nominally correct fixed_but_fugly = subprocess.run('dig +short stackoverflow.com', shell=True, # Probably don't forget these, too check=True, text=True) 4 và # XXX AVOID THIS BUG buggy = subprocess.run('dig +short stackoverflow.com') # XXX AVOID THIS BUG TOO broken = subprocess.run(['dig', '+short', 'stackoverflow.com'], shell=True) # XXX DEFINITELY AVOID THIS pathological = subprocess.run(['dig +short stackoverflow.com'], shell=True) correct = subprocess.run(['dig', '+short', 'stackoverflow.com'], # Probably don't forget these, too check=True, text=True) # XXX Probably better avoid shell=True # but this is nominally correct fixed_but_fugly = subprocess.run('dig +short stackoverflow.com', shell=True, # Probably don't forget these, too check=True, text=True) 5Kể từ thời gian vĩnh cửu (tốt, kể từ Python 2.5), tài liệu mô -đun 3 đã chứa khuyến nghị để thích 2 hơn 4:
Các vấn đề với 7 là nó rõ ràng phụ thuộc vào hệ thống và không cung cấp các cách để tương tác với quy trình con. Nó chỉ đơn giản là chạy, với đầu ra tiêu chuẩn và lỗi tiêu chuẩn ngoài tầm với của Python. Thông tin duy nhất Python nhận lại là trạng thái thoát của lệnh (0 có nghĩa là thành công, mặc dù ý nghĩa của các giá trị khác không cũng phụ thuộc vào hệ thống).PEP-324 (đã được đề cập ở trên) chứa một lý do chi tiết hơn về lý do tại sao 8 là vấn đề và cách 2 cố gắng giải quyết các vấn đề đó. 5 đã từng nản lòng hơn nữa:
Tuy nhiên, vì đôi khi trong Python 3, nó đã được thực hiện lại khi chỉ sử dụng 2 và chuyển hướng đến tài liệu 3 để biết chi tiết.Hiểu và thường sử dụng subprocess.run(''' # This for loop syntax is Bash only for((i=1;i<=$#;i++)); do # Arrays are Bash-only array[i]+=123 done''', shell=True, check=True, executable='/bin/bash') 4Bạn cũng sẽ nhận thấy rằng 2 có nhiều hạn chế tương tự như 4. Khi sử dụng thường xuyên, bạn thường nên kiểm tra xem quá trình đã hoàn thành thành công, mà 1 và 7 có (trong đó quá trình sau cũng trả về đầu ra tiêu chuẩn của quá trình phụ hoàn thành). Tương tự, bạn thường nên sử dụng 4 với 0 trừ khi bạn cụ thể cần cho phép quy trình con trả về trạng thái lỗi.Trong thực tế, với 4 hoặc 2, Python sẽ ném ngoại lệ 3 nếu quá trình phụ trả về trạng thái thoát khác không.Một lỗi phổ biến với 0 là bỏ qua 4 và sẽ ngạc nhiên khi mã xuôi dòng không thành công nếu quá trình phụ thất bại.Mặt khác, một vấn đề phổ biến với 6 và 7 là người dùng sử dụng một cách mù quáng các chức năng này đã rất ngạc nhiên khi ngoại lệ được nêu ra, ví dụ: Khi 8 không tìm thấy một trận đấu. (Có lẽ bạn nên thay thế 8 bằng mã Python gốc, như được nêu dưới đây.)Tất cả mọi thứ được tính, bạn cần hiểu cách các lệnh shell trả về mã thoát và trong những điều kiện nào chúng sẽ trả lại mã thoát khác không (lỗi) và đưa ra quyết định có ý thức về cách xử lý chính xác. Hiểu và có thể sử dụng # XXX AVOID THIS BUG buggy = subprocess.run('dig +short stackoverflow.com') # XXX AVOID THIS BUG TOO broken = subprocess.run(['dig', '+short', 'stackoverflow.com'], shell=True) # XXX DEFINITELY AVOID THIS pathological = subprocess.run(['dig +short stackoverflow.com'], shell=True) correct = subprocess.run(['dig', '+short', 'stackoverflow.com'], # Probably don't forget these, too check=True, text=True) # XXX Probably better avoid shell=True # but this is nominally correct fixed_but_fugly = subprocess.run('dig +short stackoverflow.com', shell=True, # Probably don't forget these, too check=True, text=True) 6 aka # XXX AVOID THIS BUG buggy = subprocess.run('dig +short stackoverflow.com') # XXX AVOID THIS BUG TOO broken = subprocess.run(['dig', '+short', 'stackoverflow.com'], shell=True) # XXX DEFINITELY AVOID THIS pathological = subprocess.run(['dig +short stackoverflow.com'], shell=True) correct = subprocess.run(['dig', '+short', 'stackoverflow.com'], # Probably don't forget these, too check=True, text=True) # XXX Probably better avoid shell=True # but this is nominally correct fixed_but_fugly = subprocess.run('dig +short stackoverflow.com', shell=True, # Probably don't forget these, too check=True, text=True) 7Kể từ Python 3, chuỗi bên trong Python là chuỗi Unicode. Nhưng không có gì đảm bảo rằng một quy trình con tạo ra đầu ra unicode hoặc chuỗi. . ) Sâu thẳm, Python phải lấy bộ đệm 2 và giải thích nó bằng cách nào đó. Nếu nó chứa một đốm dữ liệu nhị phân, nó không nên được giải mã thành một chuỗi unicode, bởi vì đó là hành vi dễ bị lỗi và gây lỗi-chính xác là loại hành vi phiền phức đã đánh đố nhiều tập lệnh Python 2, trước khi có cách nào Phân biệt đúng giữa văn bản được mã hóa và dữ liệu nhị phân.Với 6, bạn nói với Python rằng trên thực tế, bạn mong đợi dữ liệu văn bản trở lại trong mã hóa mặc định của hệ thống và nó nên được giải mã thành chuỗi python (unicode) với khả năng của Python tốt nhất (thường là UTF-8 trên bất kỳ đến ngày hệ thống, ngoại trừ có lẽ là Windows?)Nếu đó không phải là những gì bạn yêu cầu trở lại, Python sẽ chỉ cung cấp cho bạn các chuỗi ____72 trong chuỗi 5 và 6. Có thể tại một số điểm sau bạn biết rằng chúng là chuỗi văn bản, và bạn biết mã hóa của chúng. Sau đó, bạn có thể giải mã chúng.
Python 3.7 đã giới thiệu bí danh ngắn hơn và mô tả hơn và dễ hiểu hơn 7 cho đối số từ khóa mà trước đây có phần gây hiểu lầm 8.Hiểu # XXX AVOID THIS BUG buggy = subprocess.run('dig +short stackoverflow.com') # XXX AVOID THIS BUG TOO broken = subprocess.run(['dig', '+short', 'stackoverflow.com'], shell=True) # XXX DEFINITELY AVOID THIS pathological = subprocess.run(['dig +short stackoverflow.com'], shell=True) correct = subprocess.run(['dig', '+short', 'stackoverflow.com'], # Probably don't forget these, too check=True, text=True) # XXX Probably better avoid shell=True # but this is nominally correct fixed_but_fugly = subprocess.run('dig +short stackoverflow.com', shell=True, # Probably don't forget these, too check=True, text=True) 8 vs # XXX AVOID THIS BUG buggy = subprocess.run('dig +short stackoverflow.com') # XXX AVOID THIS BUG TOO broken = subprocess.run(['dig', '+short', 'stackoverflow.com'], shell=True) # XXX DEFINITELY AVOID THIS pathological = subprocess.run(['dig +short stackoverflow.com'], shell=True) correct = subprocess.run(['dig', '+short', 'stackoverflow.com'], # Probably don't forget these, too check=True, text=True) # XXX Probably better avoid shell=True # but this is nominally correct fixed_but_fugly = subprocess.run('dig +short stackoverflow.com', shell=True, # Probably don't forget these, too check=True, text=True) 9Với 8, bạn chuyển một chuỗi duy nhất cho vỏ của bạn và vỏ lấy nó từ đó.Với 9, bạn chuyển một danh sách các đối số cho HĐH, bỏ qua vỏ.Khi bạn không có vỏ, bạn sẽ tiết kiệm một quy trình và loại bỏ một lượng phức tạp ẩn khá đáng kể, có thể hoặc không thể chứa các lỗi hoặc thậm chí các vấn đề bảo mật. Mặt khác, khi bạn không có vỏ, bạn không chuyển hướng, mở rộng thẻ đại diện, kiểm soát công việc và một số lượng lớn các tính năng vỏ khác. Một sai lầm phổ biến là sử dụng 8 và sau đó vẫn chuyển Python một danh sách các mã thông báo hoặc ngược lại. Điều này xảy ra trong một số trường hợp, nhưng thực sự không được xác định và có thể phá vỡ theo những cách thú vị.
Câu trả lời chung "nhưng nó hoạt động đối với tôi" không phải là một phản bác hữu ích trừ khi bạn hiểu chính xác trong hoàn cảnh nào nó có thể ngừng hoạt động. Để tóm tắt ngắn gọn, việc sử dụng đúng trông giống như
Nếu bạn muốn tránh vỏ nhưng quá lười biếng hoặc không chắc chắn làm thế nào để phân tích một chuỗi vào danh sách các mã thông báo, hãy lưu ý rằng 4 có thể làm điều này cho bạn.
5 thông thường sẽ không hoạt động ở đây, bởi vì nó không bảo tồn trích dẫn. Trong ví dụ trên, hãy chú ý cách 6 là một chuỗi duy nhất.Ví dụ tái cấu trúcRất thường xuyên, các tính năng của vỏ có thể được thay thế bằng mã Python gốc. Các tập lệnh AWK hoặc 7 đơn giản có lẽ chỉ nên được dịch sang Python thay thế.Để minh họa một phần điều này, đây là một ví dụ điển hình nhưng hơi ngớ ngẩn liên quan đến nhiều tính năng vỏ.
Một số điều cần lưu ý ở đây:
Mã được tái cấu trúc cũng minh họa cho bao nhiêu vỏ thực sự cho bạn với một cú pháp rất ngắn - để tốt hơn hoặc tồi tệ hơn. Python nói rõ ràng là tốt hơn so với tiềm ẩn nhưng mã Python khá dài dòng và được cho là phức tạp hơn điều này thực sự. Mặt khác, nó cung cấp một số điểm mà bạn có thể nắm quyền kiểm soát ở giữa một thứ khác, như được minh họa một cách tầm thường bởi sự nâng cao mà chúng ta có thể dễ dàng bao gồm tên máy chủ cùng với đầu ra lệnh shell. . Cấu trúc vỏ chungĐể hoàn thiện, đây là những giải thích ngắn gọn về một số tính năng vỏ này và một số ghi chú về cách chúng có thể được thay thế bằng các cơ sở Python bản địa.
Hiểu sự khác biệt giữa subprocess.run("string for 'the shell' to parse", shell=True) # or subprocess.run(["list", "of", "tokenized strings"]) # shell=False 0 và bash 2 chạy các lệnh shell của bạn với 18 trừ khi bạn yêu cầu cụ thể khác (ngoại trừ tất nhiên trên Windows, trong đó nó sử dụng giá trị của biến 19). Điều này có nghĩa là các tính năng chỉ khác nhau như mảng, 20, vv không có sẵn.Nếu bạn cần sử dụng cú pháp chỉ dành cho Bash, bạn có thể truyền qua đường dẫn đến vỏ dưới dạng 21 (tất nhiên nếu Bash của bạn được cài đặt ở một nơi khác, bạn cần điều chỉnh đường dẫn).
A subprocess.run(shlex.split("no string for 'the shell' to parse")) # shell=False # equivalent to # subprocess.run(["no", "string", "for", "the shell", "to", "parse"]) 2 tách biệt với cha mẹ của nó và không thể thay đổi nóMột sai lầm hơi phổ biến là làm điều gì đó như
Điều tương tự sẽ xảy ra nếu quy trình con đầu tiên cố gắng thiết lập một biến môi trường, tất nhiên điều này sẽ biến mất khi bạn chạy một quy trình con khác, v.v. Một quá trình con chạy hoàn toàn tách biệt với Python và khi nó kết thúc, Python không biết nó đã làm gì (ngoài các chỉ số mơ hồ mà nó có thể suy ra từ trạng thái thoát và đầu ra từ quá trình con). Một đứa trẻ nói chung không thể thay đổi môi trường của cha mẹ; Nó không thể đặt một biến, thay đổi thư mục làm việc, hoặc, bằng rất nhiều từ, giao tiếp với cha mẹ của nó mà không cần sự hợp tác từ cha mẹ. Việc sửa chữa ngay lập tức trong trường hợp cụ thể này là chạy cả hai lệnh trong một quy trình con;
Mặc dù rõ ràng trường hợp sử dụng cụ thể này không hữu ích lắm; Thay vào đó, hãy sử dụng đối số từ khóa 23 hoặc đơn giản là 24 trước khi chạy quy trình con. Tương tự, để thiết lập một biến, bạn có thể điều khiển môi trường của quy trình hiện tại (và do đó cũng là con cái của nó) thông qua
hoặc chuyển một môi trường cài đặt cho một quy trình trẻ em với
. Đừng chạy Python từ PythonĐây là lời khuyên hơi đáng ngờ; Chắc chắn có những tình huống mà nó có ý nghĩa hoặc thậm chí là một yêu cầu tuyệt đối để điều hành trình thông dịch Python như một quy trình con từ một kịch bản Python. Nhưng rất thường xuyên, cách tiếp cận chính xác chỉ đơn giản là 27 Mô -đun Python khác vào tập lệnh gọi của bạn và gọi trực tiếp các chức năng của nó.Nếu tập lệnh Python khác nằm dưới sự kiểm soát của bạn và nó không phải là một mô -đun, hãy xem xét biến nó thành một. (Câu trả lời này đã quá dài vì vậy tôi sẽ không đi sâu vào chi tiết ở đây.) Nếu bạn cần song song, bạn có thể chạy các hàm Python trong các quy trình con với mô -đun 28. Ngoài ra còn có 29 chạy nhiều tác vụ trong một quy trình duy nhất (nhẹ hơn và giúp bạn kiểm soát nhiều hơn, nhưng cũng bị hạn chế hơn trong các luồng đó trong một quy trình được ghép nối chặt chẽ và liên kết với một Gil.)
Bạn có thể chạy bash trong Python?Thực hiện một tập lệnh bash hiện có bằng mô -đun phụ Python.Chúng tôi cũng có thể thực hiện một tập lệnh Bash hiện có bằng mô -đun phụ Python.. We can also execute an existing a bash script using Python subprocess module.
Lệnh bash trong Python là gì?Định nghĩa: Python là ngôn ngữ lập trình cấp cao được thiết kế để dễ đọc và đơn giản để thực hiện.Mặc dù Bash là một trình thông dịch ngôn ngữ lệnh tương thích SH thực thi các lệnh được đọc từ đầu vào tiêu chuẩn hoặc từ một tệp.an sh-compatible command language interpreter that executes commands read from the standard input or from a file.
Python có thể chạy lệnh thiết bị đầu cuối không?Python cho phép bạn thực thi các lệnh shell, mà bạn có thể sử dụng để bắt đầu các chương trình khác hoặc quản lý tốt hơn các tập lệnh shell mà bạn sử dụng để tự động hóa.Tùy thuộc vào trường hợp sử dụng của chúng tôi, chúng tôi có thể sử dụng hệ điều hành.hệ thống (), quy trình con., which you can use to start other programs or better manage shell scripts that you use for automation. Depending on our use case, we can use os. system() , subprocess.
Tôi có thể chạy lệnh Linux trong Python không?Cách thứ hai để chạy các lệnh Linux với Python là bằng cách sử dụng mô -đun phụ mới hơn.Mô -đun này cho phép bạn sinh ra các quy trình mới, kết nối với đường ống đầu vào/đầu ra/lỗi của chúng và có được mã trả lại của chúng.Nó được tạo ra để thay thế cả hai hệ điều hành.Hệ thống () và HĐH.using the newer subprocess module. This module allows you to spawn new processes, connect to their input/output/error pipes, and obtain their return codes. It was created to replace both os. system() and os. |