Python 从stdin读取二进制数据

Python 从stdin读取二进制数据,python,python-2.x,Python,Python 2.x,在Python2.6中是否可以将stdin作为二进制数据读取?如果是,怎么做 我从中看到,这相当简单,但在2.6中实现这一点的工具似乎并不存在 如果3.1中描述的方法不可用,是否有方法关闭stdin并以二进制模式重新打开 更新 为了清楚起见,我在MS-DOS shell中使用“type”将二进制文件的内容通过管道传输到python代码中。据我所知,这应该相当于Unix“cat”命令。但是当我测试这个时,我总是得到比预期文件大小少一个字节的结果 更新#2 首先,谢谢你的回答。我正在慢慢地寻找一个真

在Python2.6中是否可以将stdin作为二进制数据读取?如果是,怎么做

我从中看到,这相当简单,但在2.6中实现这一点的工具似乎并不存在

如果3.1中描述的方法不可用,是否有方法关闭stdin并以二进制模式重新打开

更新

为了清楚起见,我在MS-DOS shell中使用“type”将二进制文件的内容通过管道传输到python代码中。据我所知,这应该相当于Unix“cat”命令。但是当我测试这个时,我总是得到比预期文件大小少一个字节的结果

更新#2

首先,谢谢你的回答。我正在慢慢地寻找一个真正的、可用的解决方案。最后,我仍在尝试构建一个自包含的JAR文件,该文件可以自动执行Python代码,不受污染地通过所有命令行参数

我之所以选择Java/JAR/Jython路径,是因为我的一个主要外部库只能作为javajar使用。但不幸的是,我是从Python开始工作的。不久前,将我的代码转换成Java可能会更容易,但既然这些东西都应该是兼容的,我想我会尝试用卡车通过它,并证明它是可以做到的

如果有人想知道,这也与我几天前提出的问题有关

这篇文章回答了其中一些问题

因此,我将尝试更新我的原始问题,并对我目前所了解的内容进行一些说明

import sys

data = sys.stdin.read(10) # Read 10 bytes from stdin
如果需要解释二进制数据,请使用
struct
模块。

使用强制Python 2将stdin、stdout和stderr视为二进制无缓冲流

C:> type mydoc.txt | python.exe -u myscript.py
如果你还需要这个。。。 这个简单的测试我用来读取二进制文件,其中包含0x1A字符

import os, sys, msvcrt

msvcrt.setmode (sys.stdin.fileno(), os.O_BINARY)
s = sys.stdin.read()
print len (s)
我的测试文件数据是:

0x23, 0x1A, 0x45
在未将stdin设置为二进制模式的情况下,此测试在将0x1A视为EOF时立即打印1。 当然,它只在windows上工作,因为它依赖于msvcrt模块。

来自文档(请参阅):

标准流处于文本模式 默认情况下。写入或读取二进制文件 对于这些数据,请使用底层 二进制缓冲区。例如,写作 字节到标准输出,使用
sys.stdout.buffer.write(b'abc')

但是,正如公认的答案一样,使用
-u
调用python是另一个选项,它强制stdin、stdout和stderr完全无缓冲。有关详细信息,请参见python(1)手册页


有关文本缓冲的更多信息,请参阅,并使用
sys.stdin.detach()
从Python中禁用缓冲。

以下是Linux/Windows Python 2/3兼容代码的最后一个剪辑,用于从stdin读取数据而不损坏:

import sys

PY3K = sys.version_info >= (3, 0)

if PY3K:
    source = sys.stdin.buffer
else:
    # Python 2 on Windows opens sys.stdin in text mode, and
    # binary data that read from it becomes corrupted on \r\n
    if sys.platform == "win32":
        # set sys.stdin to binary mode
        import os, msvcrt
        msvcrt.setmode(sys.stdin.fileno(), os.O_BINARY)
    source = sys.stdin

b = source.read()

您可以通过以下方式执行无缓冲读取:

os.read(0,字节到字节读取)


0是stdin的文件描述符

如果我随后调用sys.stdin.read()而不带任何参数,它应该读取通过管道传入的所有二进制数据,对吗?那么,如何正确确定长度?如果数据的最后一个字节为零,则len(data)返回不正确的值。如何检查和纠正这种情况?
len
计算字符串中的\x00个字符。Python没有以null结尾的字符串
len(“Hello\x00”)==6
我想知道是不是MS-DOS shell的“type”命令导致了最后一个字节的丢失?我想我必须在Linux上测试同等的软件。谢谢。我认为这个答案没有抓住问题的关键:如果流处于“文本”模式,则
read()
的结果可能与流处于“二进制”模式时的结果不同。它可能会损坏Windows上的输入流,例如,
'\r\n'
->
'\n'
。另外,在Python3上,sys.stdin.read()返回Unicode字符串,例如
b'\xf0\x9f\x96\x96'
->'\U0001f596'(4个字节->1个字符)。如果输入不是文本,这是不受欢迎的行为。我已经用“type”测试过了,它似乎有效。也就是说,如果我不使用-u标志,每行就少了一个字符。不确定这是否有帮助。更简单的是,您需要做的只是:sys.stdin=os.fdopen(sys.stdin.fileno(),'rb',0),它将以无缓冲的'二进制'模式重新打开fd。@beav:奇怪的是,这在我的系统上不起作用。我不知道这是因为我使用的是CPython而不是Jython,还是因为我运行的是Windows XP Pro,“类型”的行为不同,还是因为Manassas区域存在磁异常,使得计算机做不同的事情。FWIW,我尝试了多种方法让Python在解释器启动后更改文件模式,包括通过ctypes访问C运行时的“setmode”函数。对我来说什么都不管用。我感觉到一个可移植性问题。谢谢你的信息。我想我必须在多个平台上做一些相当严格的测试。我希望这与使用中的JVM无关。该文档导致了py3k文档,而不是OP想要处理的内容。我尝试了使用PythonV3.2.5的
-u
,但没有任何用处。但是使用
sys.stdout.buffer
效果很好,尽管在Python 2.7.8上没有这样的功能。OP的问题是关于Python 2.6的。但是Windows是大多数人会遇到问题的唯一系统,因此,这应该是一个可接受的解决方案。这是Python2在Windows上从stdin检索原始字节的正确解决方案。在Unix上,二进制模式和普通模式之间没有区别。查看此线程:(在原始(二进制)模式下重新打开stdin?)我在Windows上遇到一个
ValueError:unsecure string pickle
异常,当尝试取消
pickle
数据时,该数据已在一个进程中写入
stdout
,该进程正在通过管道传输到另一个进程。解决方案变成了你