2013-08-14 36 views
24

Tôi muốn chạy tiện ích đếm từ Linux wc để xác định số dòng hiện tại trong/var/log/syslog, vì vậy tôi có thể phát hiện rằng nó đang phát triển. Tôi đã thử các thử nghiệm khác nhau và trong khi tôi nhận được kết quả từ wc, nó bao gồm cả số lượng dòng cũng như lệnh (ví dụ: var/log/syslog).Đầu ra của Python3 subprocess

Vì vậy, nó trở về: 1338/var/log/syslog Nhưng tôi chỉ muốn đếm dòng, vì vậy tôi muốn lột thư mục/var/log/phần syslog, và chỉ cần giữ 1338.

tôi đã cố gắng chuyển đổi nó thành chuỗi từ bytestring, và sau đó tước kết quả, nhưng không có niềm vui. Cùng một câu chuyện để chuyển đổi thành chuỗi và tước, giải mã, v.v. - tất cả đều không tạo ra kết quả mà tôi đang tìm kiếm.

Đây là một số ví dụ về những gì tôi nhận được, với 1338 dòng trong syslog:

  • b'1338/var/log/syslog \ n'
  • 1338/var/log/syslog

Dưới đây là một số mã kiểm tra tôi đã viết để thử và nứt hạt này, nhưng không có giải pháp:

import subprocess 

#check_output returns byte string 
stdoutdata = subprocess.check_output("wc --lines /var/log/syslog", shell=True) 
print("2A stdoutdata: " + str(stdoutdata)) 
stdoutdata = stdoutdata.decode("utf-8") 
print("2B stdoutdata: " + str(stdoutdata))  
stdoutdata=stdoutdata.strip() 
print("2C stdoutdata: " + str(stdoutdata))  

Kết quả từ này là:

  • 2A stdoutdata: b'1338/var/log/syslog \ n'

  • 2B stdoutdata: 1338/var/log/syslog

  • 2C stdoutdata: 1338/var/log/syslog

  • 2D stdoutdata: 1338/var/log/syslog

Trả lời

39

tôi đề nghị bạn sử dụng subprocess.getoutput() vì nó thực hiện chính xác những gì bạn muốn — chạy lệnh trong trình bao và nhận được string output của nó (trái ngược với đầu ra byte string). Sau đó, bạn có thể split on whitespace và lấy phần tử đầu tiên từ danh sách chuỗi được trả về.

Hãy thử điều này:

import subprocess 
stdoutdata = subprocess.getoutput("wc --lines /var/log/syslog") 
print("stdoutdata: " + stdoutdata.split()[0]) 
+0

Cảm ơn! Thử nghiệm nó, và nó hoạt động. Đã thực hiện rất nhiều nghiên cứu, chưa bao giờ thấy điều đó. Dang! – user2565677

+3

Bạn nên được cảnh báo rằng 'subprocess.getoutput' thuộc về thể loại của * Hàm gọi hàm Legacy * (http://docs.python.org/3/library/subprocess.html#subprocess.getoutput). – pepr

+0

@pepr Nhưng ý nghĩa 'di sản' có nghĩa là gì, thực tế nói? Tôi không thấy dòng thời gian để xóa, kể từ 3.5.0a0. (Có thể được định nghĩa ở một nơi khác không?) – belacqua

8

Để tránh cách gọi một vỏ và giải mã tên tập tin đó có thể là một chuỗi byte tùy ý (trừ '\0') trên * nix, bạn có thể vượt qua các tập tin như stdin:

import subprocess 

with open(b'/var/log/syslog', 'rb') as file: 
    nlines = int(subprocess.check_output(['wc', '-l'], stdin=file)) 
print(nlines) 

Hoặc bạn có thể bỏ qua bất kỳ lỗi giải mã nào:

import subprocess 

stdoutdata = subprocess.check_output(['wc', '-l', '/var/log/syslog']) 
nlines = int(stdoutdata.decode('ascii', 'ignore').partition(' ')[0]) 
print(nlines) 
+0

Có cách nào để có được 'sys.stdout.encoding' trong trường hợp này để chúng ta chuyển nó sang giải mã thay vì' ascii'? Nếu chúng ta 'stprocess.PIPE' stdout thì sao? –

+1

@Mr_and_Mrs_D nó sẽ là một điều sai lầm để làm: 1 - nó sẽ không giúp đỡ trong trường hợp chung (một tên tập tin có thể là một chuỗi byte đó là undecodable bởi bất kỳ mã hóa ký tự như nó được cho biết một cách rõ ràng trong câu trả lời.) 2- ascii hoạt động ở đây (để giải mã các chữ số được in bởi wc ở bất kỳ ngôn ngữ nào được Python hỗ trợ) – jfs

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