如何从 Python 文件句柄打开 .NET FileStream 对象?
How can I open a .NET FileStream object from a Python file handle?
我需要在 Python 中打开一个可写文件句柄,然后将文件描述符传递给 .NET 程序集中的一个函数(通过 pythonnet's clr
module.
访问)
从 Python 文件对象到 win32 HANDLE*
相当简单,如 this question:
所示
import clr
from Microsoft.Win32.SafeHandles import SafeFileHandle
from System.IO import FileStream, FileAccess
pyf=open("c:/temp/testing123.txt","w")
fileno=pyf.fileno()
print fileno # 6
handle = msvcrt.get_osfhandle(fileno)
print handle # 1832L
According to MSDN,现在应该可以从直接的 IntPtr
(句柄)或 SafeFileHandle
包装器构建标准的 FileStream
对象。
FileStream(IntPtr, FileAccess)
FileStream(SafeFileHandle, FileAccess)
问题是...我怎样才能说服 clr
模块将 handle
转换为 IntPtr
?
我试过以下各种版本,但它们都给我错误:
FileStream(IntPtr(handle), True)
FileStream(IntPtr(Int64(handle), True)
FileStream(IntPtr(Int32(handle), True)
SafeFileHandle(IntPtr(handle), True)
...
=> TypeError ("value cannot be converted to System.IntPtr")
关于如何将这个该死的文件句柄导入 C# 有什么建议吗?
感谢 pythonnet
mailing list 上的好心人,得到了答案。
关键是使用 Overloads
构造函数将 win32 HANDLE
强制转换为 IntPtr
类型。
这是一个完整的工作示例:
import tempfile, msvcrt
import clr, msvcrt
from System.IO import FileStream, FileAccess
from System import IntPtr
with tempfile.NamedTemporaryFile(suffix='.txt', delete=False) as pyf:
fileno=pyf.fileno()
print "fileno", fileno
handle = msvcrt.get_osfhandle(fileno)
print "HANDLE", handle
pyf.write("Python\n")
pyf.flush()
cs_handle = IntPtr.Overloads[long](handle)
cs_fs = FileStream(cs_handle, FileAccess.Write)
cs_fs.Write("CLR\n", 0, 4)
cs_fs.Flush()
print "file should contain a line from Python and a line from CLR: ", pyf.name
这个答案可能有点太晚了,但是像 this 这样的答案有用吗?
from contextlib import contextmanager
import ctypes
import io
import os, sys
import tempfile
libc = ctypes.CDLL(None)
c_stdout = ctypes.c_void_p.in_dll(libc, 'stdout')
@contextmanager
def stdout_redirector(stream):
# The original fd stdout points to. Usually 1 on POSIX systems.
original_stdout_fd = sys.stdout.fileno()
def _redirect_stdout(to_fd):
"""Redirect stdout to the given file descriptor."""
# Flush the C-level buffer stdout
libc.fflush(c_stdout)
# Flush and close sys.stdout - also closes the file descriptor (fd)
sys.stdout.close()
# Make original_stdout_fd point to the same file as to_fd
os.dup2(to_fd, original_stdout_fd)
# Create a new sys.stdout that points to the redirected fd
sys.stdout = io.TextIOWrapper(os.fdopen(original_stdout_fd, 'wb'))
# Save a copy of the original stdout fd in saved_stdout_fd
saved_stdout_fd = os.dup(original_stdout_fd)
try:
# Create a temporary file and redirect stdout to it
tfile = tempfile.TemporaryFile(mode='w+b')
_redirect_stdout(tfile.fileno())
# Yield to caller, then redirect stdout back to the saved fd
yield
_redirect_stdout(saved_stdout_fd)
# Copy contents of temporary file to the given stream
tfile.flush()
tfile.seek(0, io.SEEK_SET)
stream.write(tfile.read())
finally:
tfile.close()
os.close(saved_stdout_fd)
我需要在 Python 中打开一个可写文件句柄,然后将文件描述符传递给 .NET 程序集中的一个函数(通过 pythonnet's clr
module.
从 Python 文件对象到 win32 HANDLE*
相当简单,如 this question:
import clr
from Microsoft.Win32.SafeHandles import SafeFileHandle
from System.IO import FileStream, FileAccess
pyf=open("c:/temp/testing123.txt","w")
fileno=pyf.fileno()
print fileno # 6
handle = msvcrt.get_osfhandle(fileno)
print handle # 1832L
According to MSDN,现在应该可以从直接的 IntPtr
(句柄)或 SafeFileHandle
包装器构建标准的 FileStream
对象。
FileStream(IntPtr, FileAccess)
FileStream(SafeFileHandle, FileAccess)
问题是...我怎样才能说服 clr
模块将 handle
转换为 IntPtr
?
我试过以下各种版本,但它们都给我错误:
FileStream(IntPtr(handle), True)
FileStream(IntPtr(Int64(handle), True)
FileStream(IntPtr(Int32(handle), True)
SafeFileHandle(IntPtr(handle), True)
...
=> TypeError ("value cannot be converted to System.IntPtr")
关于如何将这个该死的文件句柄导入 C# 有什么建议吗?
感谢 pythonnet
mailing list 上的好心人,得到了答案。
关键是使用 Overloads
构造函数将 win32 HANDLE
强制转换为 IntPtr
类型。
这是一个完整的工作示例:
import tempfile, msvcrt
import clr, msvcrt
from System.IO import FileStream, FileAccess
from System import IntPtr
with tempfile.NamedTemporaryFile(suffix='.txt', delete=False) as pyf:
fileno=pyf.fileno()
print "fileno", fileno
handle = msvcrt.get_osfhandle(fileno)
print "HANDLE", handle
pyf.write("Python\n")
pyf.flush()
cs_handle = IntPtr.Overloads[long](handle)
cs_fs = FileStream(cs_handle, FileAccess.Write)
cs_fs.Write("CLR\n", 0, 4)
cs_fs.Flush()
print "file should contain a line from Python and a line from CLR: ", pyf.name
这个答案可能有点太晚了,但是像 this 这样的答案有用吗?
from contextlib import contextmanager
import ctypes
import io
import os, sys
import tempfile
libc = ctypes.CDLL(None)
c_stdout = ctypes.c_void_p.in_dll(libc, 'stdout')
@contextmanager
def stdout_redirector(stream):
# The original fd stdout points to. Usually 1 on POSIX systems.
original_stdout_fd = sys.stdout.fileno()
def _redirect_stdout(to_fd):
"""Redirect stdout to the given file descriptor."""
# Flush the C-level buffer stdout
libc.fflush(c_stdout)
# Flush and close sys.stdout - also closes the file descriptor (fd)
sys.stdout.close()
# Make original_stdout_fd point to the same file as to_fd
os.dup2(to_fd, original_stdout_fd)
# Create a new sys.stdout that points to the redirected fd
sys.stdout = io.TextIOWrapper(os.fdopen(original_stdout_fd, 'wb'))
# Save a copy of the original stdout fd in saved_stdout_fd
saved_stdout_fd = os.dup(original_stdout_fd)
try:
# Create a temporary file and redirect stdout to it
tfile = tempfile.TemporaryFile(mode='w+b')
_redirect_stdout(tfile.fileno())
# Yield to caller, then redirect stdout back to the saved fd
yield
_redirect_stdout(saved_stdout_fd)
# Copy contents of temporary file to the given stream
tfile.flush()
tfile.seek(0, io.SEEK_SET)
stream.write(tfile.read())
finally:
tfile.close()
os.close(saved_stdout_fd)