2012-02-22 36 views
18

Tôi có một trường hợp muốn thực hiện lệnh shell sau bằng Python và nhận được đầu ra,Python - làm thế nào để thực hiện các lệnh shell với đường ống?

echo This_is_a_testing | grep -c test 

tôi có thể sử dụng mã python này để thực hiện lệnh shell trên trong python,

>>> import subprocess 
>>> subprocess.check_output("echo This_is_a_testing | grep -c test", shell=True) 
'1\n' 

Tuy nhiên, vì tôi không muốn sử dụng tùy chọn "shell = True", tôi đã thử mã python sau,

>>> import subprocess 
>>> p1 = subprocess.Popen(["echo", "This_is_a_testing"], stdout=subprocess.PIPE) 
>>> p2 = subprocess.Popen(["grep", "-c", "test"], stdin=p1.stdout) 
>>> p1.stdout.close() 
>>> p2.communicate() 
(None, None) 

Tôi tự hỏi tại sao đầu ra là "Không" Tôi đã giới thiệu các mô tả trong trang web: http://docs.python.org/library/subprocess.html#subprocess.PIPE

Tôi đã bỏ lỡ một số điểm trong mã của mình chưa? Bất kỳ đề nghị/ý tưởng? Cảm ơn trước.

+0

cập nhật câu trả lời – avasal

+0

liên quan: [Làm thế nào để sử dụng subprocess.Popen để kết nối nhiều quy trình bằng ống?] (http://stackoverflow.com/q/295459/4279) – jfs

Trả lời

23

Từ hướng dẫn:

để có được bất cứ điều gì khác hơn là None trong tuple kết quả, bạn cần phải cung cấp cho stdout = PIPE và/hoặc stderr = PIPE

p2 = subprocess.Popen(["grep", "-c", "test"], stdin=p1.stdout, stdout=subprocess.PIPE) 
25

Hãy tìm tại đây:

>>> import subprocess 
>>> p1 = subprocess.Popen(["echo", "This_is_a_testing"], stdout=subprocess.PIPE) 
>>> p2 = subprocess.Popen(["grep", "-c", "test"], stdin=p1.stdout) 
>>> 1 
p1.stdout.close() 
>>> p2.communicate() 
(None, None) 
>>> 

tại đây bạn nhận được 1 là đầu ra sau khi viết p2 = subprocess.Popen(["grep", "-c", "test"], stdin=p1.stdout), Đừng bỏ qua đầu ra này trong ngữ cảnh của câu hỏi của bạn.

Nếu đây là những gì bạn muốn, sau đó vượt qua stdout=subprocess.PIPE như là đối số vào thứ hai Popen:

>>> p1 = subprocess.Popen(["echo", "This_is_a_testing"], stdout=subprocess.PIPE) 
>>> p2 = subprocess.Popen(["grep", "test"], stdin=p1.stdout, stdout=subprocess.PIPE) 
>>> p2.communicate() 
('This_is_a_testing\n', None) 
>>> 
+0

Bây giờ tôi biết rằng để 'p2.communicate()' hoạt động, tôi phải thêm 'stdout = subprocess.PIPE' vào mã' p2 = ... '. Cảm ơn. – user1129812

+0

Làm thế nào tôi có thể gặp lỗi nếu nó xảy ra trong kết quả p1? Đây là câu hỏi của tôi, bạn có thể giúp với nó? http://stackoverflow.com/questions/40467105/how-to-catch-ping-error-with-python –

8
>>> import subprocess 

>>> mycmd=subprocess.getoutput('df -h | grep home | gawk \'{ print $1 }\' | cut -d\'/\' -f3') 

>>> mycmd 

'sda6' 

>>> 
+0

nó sử dụng vỏ bên trong. OP đã nói rõ ràng: * "Tôi không muốn sử dụng tùy chọn" shell = True "" * – jfs

+1

Cảm ơn bạn. Đó là chính xác những gì tôi đang tìm kiếm khi tìm kiếm "*** cách thực hiện các lệnh shell với các đường ống ***" bằng Python. – xpt

+2

Tôi đã phải sử dụng commands.getoutput thay vì subprocess.getoutput để làm việc này – Anake

1

Trong khi trả lời chấp nhận là chính xác/làm việc, tùy chọn khác sẽ được sử dụng phương pháp Popen.communicate() để chuyển một cái gì đó đến một quá trình 'stdin:

>>> import subprocess 
>>> p2 = subprocess.Popen(["grep", "-c", "test"], stdin=subprocess.PIPE, stdout=subprocess.PIPE) 
>>> p2.communicate("This_is_a_testing") 
('1\n', None) 
>>> print p2.returncode 
0 
>>>> 

Điều này giải quyết sự cần thiết phải thực hiện một lệnh khác để chuyển hướng nó ra đặt, nếu đầu ra đã được biết đến trong kịch bản python.

Tuy nhiên communicate có tác dụng phụ, nó chờ quá trình chấm dứt. Nếu thực thi không đồng bộ là cần thiết/mong muốn bằng cách sử dụng hai quy trình có thể là lựa chọn tốt hơn.

-1

Tôi đã thử sh -c "echo 1| grep 1" và đã thành công. như thế này: result=subprocess.Popen(['sh','-c',"\"\"echo 1|grep 1\"\""], stdout=subprocess.PIPE).communicate()[0]

Các vấn đề liên quan