2010-03-23 34 views
205

Tôi đang cố gắng thực hiện cuộc gọi hệ thống bằng Python và lưu đầu ra vào chuỗi mà tôi có thể thao tác trong chương trình Python.Đầu ra cửa hàng của subprocess.Popen gọi trong một chuỗi

#!/usr/bin/python 
import subprocess 
p2 = subprocess.Popen("ntpq -p") 

Tôi đã thử một vài điều trong đó có một số những gợi ý ở đây:

Retrieving the output of subprocess.call()

nhưng không có bất kỳ may mắn.

+1

Nó luôn luôn là tốt để đăng mã thực tế bạn chạy và traceback thực tế hoặc bahaviour bất ngờ cho các câu hỏi cụ thể như thế này. Ví dụ, tôi không biết những gì bạn đã cố gắng làm để có được kết quả đầu ra và tôi nghi ngờ bạn đã không thực sự đạt được điều đó để bắt đầu - bạn sẽ gặp lỗi khi không tìm tập tin cho '" ntpq -p "' , đó là một phần khác của vấn đề bạn đang hỏi. –

Trả lời

356

Trong Python 2.7 hoặc Python 3

Thay vì thực hiện một đối tượng Popen trực tiếp, bạn có thể sử dụng subprocess.check_output() function để lưu trữ sản phẩm của một lệnh trong một chuỗi:

from subprocess import check_output 
out = check_output(["ntpq", "-p"]) 

Trong Python 2.4 -2.6

Sử dụng phương pháp communicate.

import subprocess 
p = subprocess.Popen(["ntpq", "-p"], stdout=subprocess.PIPE) 
out, err = p.communicate() 

out là những gì bạn muốn.

Lưu ý quan trọng về câu trả lời khác

Lưu ý làm thế nào tôi trôi qua trong lệnh. Ví dụ "ntpq -p" đưa ra một vấn đề khác. Vì Popen không gọi trình bao, bạn sẽ sử dụng danh sách lệnh và tùy chọn— ["ntpq", "-p"].

+2

Trong trường hợp này, không python chờ đợi cho hệ thống này gọi để kết thúc? Hoặc là cần thiết để gọi một cách rõ ràng chức năng wait/waitpid? – NoneType

+5

@NoneType, 'Popen.communicate' không trở lại cho đến khi quá trình chấm dứt. –

+8

nếu bạn muốn nhận được lỗi dòng thêm stderr: 'p = subprocess.Popen ([" ntpq "," -p "], stdout = subprocess.PIPE, stderr = subprocess.PIPE) ' – Tim

32

này làm việc cho tôi cho chuyển hướng stdout (stderr thể được xử lý tương tự):

from subprocess import Popen, PIPE 
pipe = Popen(path, stdout=PIPE) 
text = pipe.communicate()[0] 

Nếu nó không làm việc cho bạn, hãy xác định chính xác vấn đề bạn đang gặp phải.

+3

Điều này tạo ra một số đối tượng lạ. Khi tôi chuyển đổi nó thành chuỗi, nó thoát khoảng trắng như '\ n'. –

19

Giả sử rằng pwd chỉ là một ví dụ, đây là cách bạn có thể làm điều đó:

import subprocess 

p = subprocess.Popen("pwd", stdout=subprocess.PIPE) 
result = p.communicate()[0] 
print result 

Xem subprocess documentation cho another example và biết thêm thông tin.

4
import os 
list = os.popen('pwd').read() 

Trong trường hợp này, bạn sẽ chỉ có một phần tử trong danh sách.

+5

'os.popen' không được hỗ trợ cho mô đun' subprocess'. –

+2

Điều này khá hữu ích đối với quản trị viên trên một hộp cũ sử dụng chuỗi phiên bản 2.2.X của Python. –

15

subprocess.Popen: http://docs.python.org/2/library/subprocess.html#subprocess.Popen

import subprocess 

command = "ntpq -p" # the shell command 
process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=None, shell=True) 

#Launch the shell command: 
output = process.communicate() 

print output[0] 

Trong constructor Popen, nếu vỏĐúng, bạn nên thông qua các lệnh như là một chuỗi chứ không phải là một chuỗi. Nếu không, chỉ cần tách lệnh vào một danh sách:

command = ["ntpq", "-p"] # the shell command 
process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=None) 

Nếu bạn cần phải đọc cũng sai số chuẩn, vào khởi Popen, bạn có thể đặt stderr-subprocess.PIPE hoặc subprocess.STDOUT:

import subprocess 

command = "ntpq -p" # the shell command 
process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) 

#Launch the shell command: 
output, error = process.communicate() 
+0

+1 cho đối số vỏ –

3

Tôi đã viết một chức năng nhỏ dựa trên câu trả lời khác ở đây:

def pexec(*args): 
    return subprocess.Popen(args, stdout=subprocess.PIPE).communicate()[0].rstrip() 

Cách sử dụng:

changeset = pexec('hg','id','--id') 
branch = pexec('hg','id','--branch') 
revnum = pexec('hg','id','--num') 
print('%s : %s (%s)' % (revnum, changeset, branch)) 
10

này hoạt động hoàn hảo đối với tôi :

import subprocess 
try: 
    #prints results and merges stdout and std 
    result = subprocess.check_output("echo %USERNAME%", stderr=subprocess.STDOUT, shell=True) 
    print result 
    #causes error and merges stdout and stderr 
    result = subprocess.check_output("copy testfds", stderr=subprocess.STDOUT, shell=True) 
except subprocess.CalledProcessError, ex: # error code <> 0 
    print "--------error------" 
    print ex.cmd 
    print ex.message 
    print ex.returncode 
    print ex.output # contains stdout and stderr together 
3

Điều này hoàn hảo cho tôi. Bạn sẽ nhận được mã trả lại, stdout và stderr trong một bộ dữ liệu.

from subprocess import Popen, PIPE 

def console(cmd): 
    p = Popen(cmd, shell=True, stdout=PIPE) 
    out, err = p.communicate() 
    return (p.returncode, out, err) 

Ví dụ:

result = console('ls -l') 
print 'returncode: %s' % result[0] 
print 'output: %s' % result[1] 
print 'error: %s' % result[2] 
7

cho Python 2.7+ câu trả lời thành ngữ là sử dụng subprocess.check_output()

Bạn cũng nên lưu ý việc xử lý các đối số khi gọi một tiến trình con, vì nó có thể có một chút khó hiểu ....

Nếu args chỉ là một lệnh duy nhất không có args của chính nó (hoặc bạn có shell=True thiết lập), nó có thể là một chuỗi. Nếu không, nó phải là một danh sách.

ví dụ ... để gọi lệnh ls, điều này là tốt:

from subprocess import check_call 
check_call('ls') 

nên là thế này:

from subprocess import check_call 
check_call(['ls',]) 

tuy nhiên, nếu bạn muốn vượt qua một số args để lệnh shell , bạn không thể làm điều này:

from subprocess import check_call 
check_call('ls -al') 

ins tead, bạn phải vượt qua nó như là một danh sách:

from subprocess import check_call 
check_call(['ls', '-al']) 

các shlex.split() chức năng đôi khi có thể hữu ích để tách một chuỗi thành cú pháp vỏ như trước đây tạo ra một quy trình con ... như thế này:

from subprocess import check_call 
import shlex 
check_call(shlex.split('ls -al')) 
+0

Năm năm sau, câu hỏi này vẫn nhận được rất nhiều tình yêu. Cảm ơn bạn đã cập nhật 2.7+, Corey! – Mark

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