Làm thế nào để ghi dữ liệu nhị phân vào stdout trong python 3?


103

Trong python 2.x, tôi có thể làm điều này:

import sys, array
a = array.array('B', range(100))
a.tofile(sys.stdout)

Tuy nhiên, bây giờ tôi nhận được một TypeError: can't write bytes to text stream. Có một số mã hóa bí mật mà tôi nên sử dụng không?


4
Sẽ tốt hơn nhiều để tìm một câu trả lời rằng sẽ làm việc với Python 2.6+ và 3.x
Sorin

2
os.writesẽ hoạt động trên cả Py2 và Py3.
David Wolever

Câu trả lời:


169

Một cách tốt hơn:

import sys
sys.stdout.buffer.write(b"some binary data")

4
Việc sử dụng sys.stdout.buffercũng cho phép bạn thực hiện những việc như sử dụng shutil.copyfileobjngay cả khi đối tượng tệp nguồn cung cấp byte chứ không phải chuỗi. +1
csl

1
Các chương trình sử dụng điều này không thể được kiểm tra trong IDLE 3:AttributeError: 'PseudoOutputFile' object has no attribute 'buffer'
Damian Yerrick

4
@DamianYerrick trong IDLE (ít nhất là trong Windows) pythonw.exechạy IDLE, có nghĩa là không có stdout. Nó được mô phỏng bằng tkinter. Về mặt vật lý, nó không thể xử lý các byte. Trong trường hợp này, .decode('UTF-8', errors='replace')chuỗi của bạn hoặc chạy python3 -I <filename>để lấy REPL thay vì sử dụng IDLE.
Artyer

Lộn xộn thứ tự ghi khi viết tới stderrnếu sử dụng cùng với print(file=sys.stderr).
Kotauskas 19/07/19

15
import os
os.write(1, a.tostring())

hoặc, os.write(sys.stdout.fileno(), …)nếu điều đó dễ đọc hơn 1đối với bạn.


Cảm ơn, điều đó đã hiệu quả. Cảm thấy có một chút hack-ish nhưng tôi đoán đó không phải là điều phổ biến để làm.
Ivan Baldin

6
Vấn đề os.writelà bạn sẽ phải kiểm tra giá trị trả về, vì nó không đảm bảo rằng mọi thứ sẽ được viết.
mic_e

10

Một cách thành ngữ để làm như vậy, chỉ có sẵn cho Python 3, là:

with os.fdopen(sys.stdout.fileno(), "wb", closefd=False) as stdout:
    stdout.write(b"my bytes object")
    stdout.flush()

Phần tốt là nó sử dụng giao diện đối tượng tệp bình thường, mà mọi người đã quen với Python.

Lưu ý rằng tôi đang cài đặt closefd=Falseđể tránh đóng sys.stdoutkhi thoát khỏi withkhối. Nếu không, chương trình của bạn sẽ không thể in ra stdout nữa. Tuy nhiên, đối với các loại trình mô tả tệp khác, bạn có thể muốn bỏ qua phần đó.


Tại sao bạn tuôn ra? Không phải tốt hơn nếu để Python quyết định thời điểm xả stdout?
Martin

0

Trong trường hợp bạn muốn chỉ định mã hóa trong python3, bạn vẫn có thể sử dụng lệnh byte như bên dưới:

import os
os.write(1,bytes('Your string to Stdout','UTF-8'))

trong đó 1 là số thông thường tương ứng cho stdout -> sys.stdout.fileno ()

Ngược lại, nếu bạn không quan tâm đến mã hóa, chỉ cần sử dụng:

import sys
sys.stdout.write("Your string to Stdout\n")

Nếu bạn muốn sử dụng os.write mà không cần mã hóa, hãy thử sử dụng cách bên dưới:

import os
os.write(1,b"Your string to Stdout\n")

1
Các chương trình sử dụng os.write(sys.stdout.fileno(), some_bytes)sẽ không hoạt động trong IDLE. io.UnsupportedOperation: fileno
Damian Yerrick

@DamianYerrick: Bạn nói đúng ... IDLE không nên được sử dụng để kiểm tra một cái gì đó như vậy. Trong thời gian ngắn: hãy thử mở IDLE (tôi đã có trình bao python3.5.1) và chỉ cần nhập sys và sys.stdout.fileno (), nó sẽ khiến bạn gặp lỗi, vì trong IDLE, thao tác này không được hỗ trợ :-) Điều này luôn quan trọng để nhớ bạn đang làm việc trong môi trường nào và cố gắng đạt được những gì có thể;) Hy vọng điều này làm rõ truy vấn của bạn :-) Chúc một ngày cuối tuần vui vẻ.
Marco smdm

Bạn chỉ đề cập đến một cách ghi dữ liệu nhị phân thực tế vào stdout, cách cuối cùng.
Kotauskas 19/07/19
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.