如何在 Windows 上的 Python 中捕获 DLL 的 stdout 和/或 stderr?例如,这将
"hello"
打印到 stderr,但应该可以将 "hello"
捕获为字符串而不是打印它:
import ctypes
string = b'hello\n'
ctypes.cdll.msvcrt._write(2, string, len(string))
这是行不通的:
sys.stderr
分配给 StringIO
(或等效地,使用 contextlib.redirect_stdout
)不会捕获输出,因为它来自 C 库函数,而不是 Python print 语句。这在 Linux 上也不起作用。的建议,使用
os.dup2()
并从单独线程上的管道读取,只会抑制输出而不捕获它。here的建议使用
ctypes.cdll.kernel32.GetStdHandle()
和ctypes.cdll.kernel32.SetStdHandle()
,在尝试打印到修改后的stderr时会给出错误OSError: [WinError 6] The handle is invalid
。ctypes.util.find_msvcrt()
在 Python 3.5+ 中返回 None
,据我了解,这是因为 Microsoft 已从 Microsoft Visual C++ Runtime (MSVCRT) 过渡到 Universal C Runtime (UCRT)。即使我将行 msvcrt = CDLL(ctypes.util.find_msvcrt())
更改为 msvcrt = ctypes.cdll.msvcrt
,它也只是抑制输出而不捕获它。我的总体印象是,适用于 Linux 的解决方案不适用于 Windows,并且由于过渡到 UCRT,过去适用于 Windows 的解决方案不再适用。
这并不完全是你想要的,但你也许可以将你的 dll 调用包装在
subprocess
import subprocess
p = subprocess.Popen(
["python3"],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
text=True, # optional avoids .encode/decode
)
data = r"""
import ctypes
string = b'hello\n'
ctypes.cdll.msvcrt._write(2, string, len(string))
"""
out, err = p.communicate(data)
if p.returncode != 0:
print("failed!")
print(out)
print(err)