2009-03-30 32 views
44

Tôi có một tệp nhị phân có tên A tạo ra kết quả khi được gọi. Nếu tôi gọi nó từ một vỏ Bash, phần lớn đầu ra bị chặn bởi A > /dev/null. Tất cả đầu ra bị chặn bởi A &> /dev/nullNgăn chặn đầu ra trong các cuộc gọi Python đến các tệp thực thi

Tôi có một tập lệnh python có tên B cần gọi A. Tôi muốn có thể tạo ra đầu ra từ B, trong khi triệt tiêu tất cả đầu ra từ A.

Từ bên trong B, tôi đã cố gắng os.system('A'), os.system('A > /dev/null'), và os.system('A &> /dev/null'), os.execvp('...'), vv nhưng không ai trong số những người ngăn chặn tất cả các đầu ra từ A.

tôi có thể chạy B &> /dev/null, nhưng điều đó ngăn chặn tất cả các B ' s đầu ra quá và tôi không muốn điều đó.

Mọi người đều có đề xuất?

Trả lời

57

Nếu bạn có Python 2.4, bạn có thể sử dụng the subprocess module:

>>> import subprocess 
>>> s = subprocess.Popen(['cowsay', 'hello'], \ 
     stderr=subprocess.STDOUT, stdout=subprocess.PIPE).communicate()[0] 
>>> print s 
_______ 
<hello> 
------- 
     \ ^__^ 
     \ (oo)\_______ 
      (__)\  )\/\ 
       ||----w | 
       ||  || 
+0

Tôi đã thử điều này và nó hoạt động, cảm ơn! – Lin

+57

+1 for cowsay :) – MestreLion

+7

Điều này sẽ hoạt động kém nếu đầu ra để stdout không bị chặn. –

8

Vì tài liệu os.system() đề cập đến, hãy sử dụng mô-đun subprocess và nếu bạn muốn, hãy đặt stdout = open (os.devnull, 'w') (và có thể tương tự cho stderr) khi bạn mở subprocess.

103
import os 
import subprocess 

command = ["executable", "argument_1", "argument_2"] 

with open(os.devnull, "w") as fnull: 
    result = subprocess.call(command, stdout = fnull, stderr = fnull) 

Nếu lệnh không có bất kỳ đối số, bạn chỉ có thể cung cấp nó như là một chuỗi đơn giản.

Nếu lệnh của bạn dựa vào các tính năng vỏ như ký tự đại diện, đường ống hoặc biến môi trường, bạn sẽ cần cung cấp toàn bộ lệnh dưới dạng chuỗi và cũng chỉ định shell = True. Điều này nên tránh, mặc dù, vì nó đại diện cho một mối nguy hiểm bảo mật nếu nội dung của chuỗi không được xác nhận một cách cẩn thận.

+0

tại sao shell = True? –

+4

Bởi vì câu hỏi ban đầu được sử dụng os.system và, không biết chính xác những gì anh ta đang làm, shell = True là bản dịch đáng tin cậy nhất cho điều đó. – DNS

+0

DNS, tôi đã thử giải pháp của bạn và nó hoạt động hoàn hảo cho tôi. Cảm ơn! – Lin

1

Tôi biết đã đến cuối trò chơi, nhưng tại sao không chỉ chuyển hướng đầu ra đến/dev/null từ bên trong os.system? Ví dụ:

tgt_file = "./bogus.txt" 
os.sytem("d2u '%s' &> /dev/null" % tgt_file) 

Điều này dường như hoạt động trong những trường hợp bạn không muốn xử lý subprocess.STDOUT.

+2

Bởi vì việc sử dụng os.system cho các cuộc gọi hệ thống sẽ không được chấp nhận. Các mô-đun xử lý con xử lý một cách thanh lịch và an toàn hơn – MestreLion

12

Nếu công cụ tìm kiếm đưa bạn đến câu hỏi cũ này (như tôi), hãy lưu ý rằng việc sử dụng PIPE có thể dẫn đến deadlocks. Thật vậy, vì các đường ống được đệm, bạn có thể viết một số byte nhất định trong một đường ống, ngay cả khi không có ai đọc nó. Tuy nhiên kích thước của bộ đệm là hữu hạn. Và do đó nếu chương trình A của bạn có đầu ra lớn hơn bộ đệm, A sẽ bị chặn bằng văn bản, trong khi chương trình gọi B chờ kết thúc của A. Nhưng không, trong trường hợp cụ thể này ... xem các bình luận bên dưới.

Tuy nhiên, tôi khuyên bạn nên sử dụng giải pháp Devin Jeanpierre và DNS '.

+0

Điều này có thực sự đúng không? Tôi nghĩ rằng nó chỉ deadlocks nếu bạn sử dụng call() hoặc popen()/wait(), nhưng không phải popen()/communication(). –

+0

Có! Để trích dẫn tài liệu, "Lưu ý Dữ liệu đọc được đệm trong bộ nhớ, do đó, không sử dụng phương pháp này nếu kích thước dữ liệu lớn hoặc không giới hạn". –

+0

"đệm trong bộ nhớ" không nhất thiết có nghĩa là đường ống bị bế tắc. Vấn đề họ đề cập đến trong tài liệu là nếu một lệnh tạo ra rất nhiều đầu ra, tất cả được lưu trữ trong bộ nhớ trên heap của python. Đây là khóa học không mong muốn, và có thể gây ra lỗi bộ nhớ hoặc thực hiện rất nặng, nhưng chỉ trong trường hợp cực đoan và bạn sẽ không gặp phải deadlocks. – Clueless

0

tôi sử dụng:

call(command, stderr=subprocess.PIPE, stdout=subprocess.PIPE) 

nơi lệnh là chuỗi các lệnh + lập luận

Để làm việc này bạn phải nhập subprocess

+1

Sẽ không bế tắc đó? –

0

Nếu bạn cần phải chỉ chụp STDOUT, doesn' t gán nó vào một biến làm điều này? Ví dụ:

megabyte='' 
# Create a 1 MiB string of NULL characters. 
for i in range(1048576): 
    megabyte += '\0' 
fh=open('zero.bin','w') 
# Write an 8 GiB file. 
for i in range(8192): 
    print(i) 
    # Suppress output of 'write()' by assigning to a variable. 
    discard=fh.write(megabyte) 
fh.close() 

tôi đã tạo ra một lượng lớn tập tin zero-điền để không gian trống trên ổ cứng của tôi và phát hiện ra rằng mỗi cuộc gọi đến handle.write (string) nhổ ra số byte bằng văn bản. Chỉ định nó cho một vairable đàn áp đầu ra đó.

21

Trong Python 3.3 trở lên, subprocess hỗ trợ an option for redirecting to /dev/null. Để sử dụng nó, khi gọi số .Popen và bạn bè, hãy chỉ định stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, làm đối số từ khóa.

Vì vậy, câu trả lời DNS, viết lại cho Python 3.3+, trở thành

import subprocess 
command = ["executable", "argument_1", "argument_2"] 
result = subprocess.call(command, 
         stdout=subprocess.DEVNULL, 
         stderr=subprocess.DEVNULL) 

Từ các tài liệu:

subprocess.DEVNULL¶

giá trị đặc biệt mà có thể được sử dụng như là stdin, stdout hoặc stderr đối số cho Popen và chỉ ra rằng tệp đặc biệt os.devnull sẽ được sử dụng.

Tính năng mới trong phiên bản 3.3.

Đối với Python 3.0 đến 3.2, bạn phải mở thủ công thiết bị rỗng bằng cách sử dụng open(os.devnull), như DNS đã viết.

+1

Thật không may, 'subprocess.DEVNULL' chỉ có sẵn trong 3.3+. Câu trả lời này nên được sửa đổi với mã tương thích (hoặc tham chiếu đến nó). Cũng không có lý do gì để sử dụng 'shell = True'. – phihag

+0

@phihag: Tôi không bao gồm mã tương thích vì câu trả lời của DNS mô tả đầy đủ cách thực hiện mà không có 'subprocess.DEVNULL'. Bạn nói đúng về 'shell'; đã sửa. –

+0

đây là một trong đó đã làm việc cho tôi, bằng cách sử dụng python3 –

0

Nếu bạn không muốn chờ lệnh hoàn thành, chẳng hạn như khởi động tác vụ sao lưu, một tùy chọn khác là chuyển nó qua bash, làm cho phép chuyển hướng hoạt động bình thường.

Ví dụ, bắt đầu từ một file âm thanh sử dụng aplay:

import os 

def PlaySound(filename): 
    command = 'bash -c "aplay %s &> /dev/null &"' % (filename) 
    os.system(command) 

Bằng cách này tôi có thể đẻ trứng một quá trình mới, không phải chờ đợi cho nó để kết thúc và ngăn chặn nó từ in ấn đến các thiết bị đầu cuối. Điểm duy nhất là nó sẽ tải một trường hợp bash cũng như quá trình bạn đang chạy, cung cấp một chi phí nhỏ.

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