使用 IronPython 将二进制数据写入标准输出

发布于 2024-09-12 08:57:15 字数 1770 浏览 7 评论 0原文

我有两个 Python 脚本,我在 Windows 上运行 .NET 2.0 上的 IronPython 2.6。一个输出二进制数据,另一个处理数据。我希望能够使用管道将数据从第一个流传输到第二个。我在这里遇到的问题是,当从 Windows 命令行运行时,sys.stdout 使用 CP437 字符编码和文本模式而不是二进制模式('w' 代替'wb')。这会导致一些大于 127 的字节被写入错误的字符(即,不同的字节值在输出中产生相同的字符,因此读取它们的脚本无法区分)。

例如,此脚本打印相同的字符(下划线)两次:

import sys
sys.stdout.write(chr(95))
sys.stdout.write(chr(222))

因此,当我尝试读取数据时,我得到的内容与我最初编写的内容不同。

我编写了这个脚本来检查问题是否出在 'w' 模式或编码下:

import sys
str = chr(222)

# try writing chr(222) in ASCII in both write modes
# ASCII is the default encoding
open('ascii_w', 'w').write(str)
open('ascii_wb', 'wb').write(str)

# set encoding to CP437 and try writing chr(222) in both modes
reload(sys)
sys.setdefaultencoding("cp437")
open('cp437_w', 'w').write(str)
open('cp437_wb', 'wb').write(str)

运行该脚本后,文件 cp437_w 包含字符 95,其他三个文件分别包含字符222。因此,我认为该问题是由CP437编码和'w'模式写入相结合引起的。在这种情况下,如果我可以强制 stdout 使用二进制模式,问题就会得到解决(我假设 cmd.exe 使用 CP437,因此不可能使用 ASCII 编码)。这就是我被困住的地方;我找不到任何方法来做到这一点。

我发现一些潜在的解决方案不起作用:

  • 运行 ipy -u 似乎没有任何效果(我还测试了它是否会导致打印 Unix 风格的换行符;它不会不,所以我怀疑 -u 根本不适用于 IronPython)
  • 我无法使用 此解决方案 因为 msvcrt IronPython
  • 与 Python 3.x 不支持,您可以通过 sys.stdout.buffer 访问无缓冲的 stdout;这在 2.6 中不可用
  • os.fdopen(sys.stdout.fileno(), 'wb', 0) 仅返回 'w'< 中的 stdout /code> 模式

所以是的,有什么想法吗?另外,如果有一种不使用 stdout 的更好的流式传输二进制数据的方法,我当然愿意接受建议。

I have two Python scripts which I am running on Windows with IronPython 2.6 on .NET 2.0. One outputs binary data and the other processes the data. I was hoping to be able to stream data from the first to the second using pipes. The problem I encountered here is that, when run from the Windows command-line, sys.stdout uses CP437 character encoding and text mode instead of binary mode ('w' instead of 'wb'). This causes some bytes greater than 127 to be written as the wrong character (i.e., different byte values produce the same character in the output and are thus indistinguishable by the script reading them).

For example, this script prints the same character (an underscore) twice:

import sys
sys.stdout.write(chr(95))
sys.stdout.write(chr(222))

So when I try to read the data I get something different than what I originally wrote.

I wrote this script to check if the problem was writing in 'w' mode or the encoding:

import sys
str = chr(222)

# try writing chr(222) in ASCII in both write modes
# ASCII is the default encoding
open('ascii_w', 'w').write(str)
open('ascii_wb', 'wb').write(str)

# set encoding to CP437 and try writing chr(222) in both modes
reload(sys)
sys.setdefaultencoding("cp437")
open('cp437_w', 'w').write(str)
open('cp437_wb', 'wb').write(str)

After running that, the file cp437_w contains character 95 and the other three each contain character 222. Therefore, I believe that the problem is caused by the combination of CP437 encoding and writing in 'w' mode. In this case it would be solved if I could force stdout to use binary mode (I'm assuming that getting it to use ASCII encoding is impossible given that cmd.exe uses CP437). This is where I'm stuck; I can't find any way to do this.

Some potential solutions I found that didn't work:

  • running ipy -u doesn't seem to have any effect (I also tested to see if it would cause Unix-style newlines to be printed; it doesn't, so I suspect that -u doesn't work with IronPython at all)
  • I can't use this solution because msvcrt is not supported in IronPython
  • with Python 3.x you can access unbuffered stdout through sys.stdout.buffer; this isn't available in 2.6
  • os.fdopen(sys.stdout.fileno(), 'wb', 0) just returns stdout in 'w' mode

So yeah, any ideas? Also, if there's a better way of streaming binary data that doesn't use stdout, I'm certainly open to suggestions.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

梦里°也失望 2024-09-19 08:57:15

sys.stdout 只是一个指向与 sys.__stdout__ 相同的变量,

因此,只需以二进制模式打开一个文件,将该文件分配给 sys.stdout 并使用它。如果您再次需要真正的、正常的标准输出,您可以使用

sys.stdout = sys.__stdout__

sys.stdout is just a variable that points to the same thing as sys.__stdout__

Therefore, just open up a file in binary mode, assign the file to sys.stdout and use it. If you ever need the real, normal stdout back again, you can get it with

sys.stdout = sys.__stdout__
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文