- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个简单的 C 扩展(参见下面的示例),有时使用 printf 函数打印。
我正在寻找一种方法来包装从该 C 扩展中对函数的调用,以便所有这些 printfs 都将被重定向到我的 python 记录器。
你好ç:
#include <Python.h>
static PyObject* hello(PyObject* self)
{
printf("example print from a C code\n");
return Py_BuildValue("");
}
static char helloworld_docs[] =
"helloworld(): Any message you want to put here!!\n";
static PyMethodDef helloworld_funcs[] = {
{"hello", (PyCFunction)hello,
METH_NOARGS, helloworld_docs},
{NULL}
};
static struct PyModuleDef cModPyDem =
{
PyModuleDef_HEAD_INIT,
"helloworld",
"Extension module example!",
-1,
helloworld_funcs
};
PyMODINIT_FUNC PyInit_helloworld(void)
{
return PyModule_Create(&cModPyDem);
};
设置.py:
from distutils.core import setup, Extension
setup(name = 'helloworld', version = '1.0', \
ext_modules = [Extension('helloworld', ['hello.c'])])
使用第一次运行
python3 setup.py install
import helloworld
helloworld.hello()
我希望能够做这样的事情:
with redirect_to_logger(my_logger)
helloworld.hello()
编辑:我看到许多帖子展示了如何使 C 中的打印静音,但我无法从中找出如何在 python 中捕获打印。
import select
import threading
import time
import logging
import re
from contextlib import contextmanager
from wurlitzer import pipes
from helloworld import hello
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')
ch.setFormatter(formatter)
logger.addHandler(ch)
class CPrintsHandler(threading.Thread):
def __init__(self, std, poll_std, err, poll_err, logger):
super(CPrintsHandler, self).__init__()
self.std = std
self.poll_std = poll_std
self.err = err
self.poll_err = poll_err
self.logger = logger
self.stop_event = threading.Event()
def stop(self):
self.stop_event.set()
def run(self):
while not self.stop_event.is_set():
# How can I poll both std and err at the same time?
if self.poll_std.poll(1):
line = self.std.readline()
if line:
self.logger.debug(line.strip())
if self.poll_err.poll(1):
line = self.err.readline()
if line:
self.logger.debug(line.strip())
@contextmanager
def redirect_to_logger(some_logger):
handler = None
try:
with pipes() as (std, err):
poll_std = select.poll()
poll_std.register(std, select.POLLIN)
poll_err = select.poll()
poll_err.register(err, select.POLLIN)
handler = CPrintsHandler(std, poll_std, err, poll_err, some_logger)
handler.start()
yield
finally:
if handler:
time.sleep(0.1) # why do I have to sleep here for the foo prints to finish?
handler.stop()
handler.join()
def foo():
logger.debug('logger print from foo()')
hello()
def main():
with redirect_to_logger(logger):
# I don't want the logs from here to be redirected as well, only printf.
logger.debug('logger print from main()')
foo()
main()
但我有几个问题:
python3 redirect_c_example_for_stackoverflow.py
最佳答案
在 Linux 上,您可以使用 wurlitzer
这将捕获 fprint
的输出,例如:
from wurlitzer import pipes
with pipes() as (out, err):
helloworld.hello()
out.read()
#'example print from a C code\n'
wurlitzer
基于
this article of Eli Bendersky ,如果您不喜欢依赖第三方库,可以使用的代码。
wurlitzer
并且文章中的代码仅适用于 Linux(和可能的 MacOS)。
ctypes
):
%%cython
import io
import os
cdef extern from *:
"""
#include <windows.h>
#include <io.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
int open_temp_file() {
TCHAR lpTempPathBuffer[MAX_PATH+1];//path+NULL
// Gets the temp path env string (no guarantee it's a valid path).
DWORD dwRetVal = GetTempPath(MAX_PATH, // length of the buffer
lpTempPathBuffer); // buffer for path
if(dwRetVal > MAX_PATH || (dwRetVal == 0))
{
return -1;
}
// Generates a temporary file name.
TCHAR szTempFileName[MAX_PATH + 1];//path+NULL
DWORD uRetVal = GetTempFileName(lpTempPathBuffer, // directory for tmp files
TEXT("tmp"), // temp file name prefix
0, // create unique name
szTempFileName); // buffer for name
if (uRetVal == 0)
{
return -1;
}
HANDLE tFile = CreateFile((LPTSTR)szTempFileName, // file name
GENERIC_READ | GENERIC_WRITE, // first we write than we read
0, // do not share
NULL, // default security
CREATE_ALWAYS, // overwrite existing
FILE_ATTRIBUTE_TEMPORARY | FILE_FLAG_DELETE_ON_CLOSE, // "temporary" temporary file, see https://docs.microsoft.com/en-us/archive/blogs/larryosterman/its-only-temporary
NULL); // no template
if (tFile == INVALID_HANDLE_VALUE) {
return -1;
}
return _open_osfhandle((intptr_t)tFile, _O_APPEND | _O_TEXT);
}
int replace_stdout(int temp_fileno)
{
fflush(stdout);
int old;
int cstdout = _fileno(stdout);
old = _dup(cstdout); // "old" now refers to "stdout"
if (old == -1)
{
return -1;
}
if (-1 == _dup2(temp_fileno, cstdout))
{
return -1;
}
return old;
}
int restore_stdout(int old_stdout){
fflush(stdout);
// Restore original stdout
int cstdout = _fileno(stdout);
return _dup2(old_stdout, cstdout);
}
void rewind_fd(int fd) {
_lseek(fd, 0L, SEEK_SET);
}
"""
int open_temp_file()
int replace_stdout(int temp_fileno)
int restore_stdout(int old_stdout)
void rewind_fd(int fd)
void close_fd "_close" (int fd)
cdef class CStdOutCapture():
cdef int tmpfile_fd
cdef int old_stdout_fd
def start(self): #start capturing
self.tmpfile_fd = open_temp_file()
self.old_stdout_fd = replace_stdout(self.tmpfile_fd)
def stop(self): # stops capturing, frees resources and returns the content
restore_stdout(self.old_stdout_fd)
rewind_fd(self.tmpfile_fd) # need to read from the beginning
buffer = io.TextIOWrapper(os.fdopen(self.tmpfile_fd, 'rb'))
result = buffer.read()
close_fd(self.tmpfile_fd)
return result
现在:
b = CStdOutCapture()
b.start()
helloworld.hello()
out = b.stop()
print("HERE WE GO:", out)
# HERE WE GO: example print from a C code
关于python-3.x - C 扩展 - 如何将 printf 重定向到 python 记录器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63112945/
我想知道以下语句在 C 中会打印什么? printf("hello\n") || (printf("goodbye\n") || printf("world\n")); 我通常习惯于使用“cout”在
这是我目前正在学习的系统编程类(class)的幻灯片: catch_child 是 SIGCHLD 处理程序。输出与代码如何对应?为什么没有打印一些“Child #x started”消息? 最佳答案
这有点像拼图……我刚刚又回到了C,打算这次掌握它。所以我一直在阅读 The C Programming Language ,我得到了这个声明: Among others, printf also re
如何使用 printf 在字符串末尾附加空格? 我找不到任何在右侧附加空格的示例。 A similar question我发现使用 printf改为在字符串的左侧添加空格。 最佳答案 使用负数左对齐(
我想通过 usart 从 stm32f405 注销。 在我的 syscall.c 文件中,我实现了通过 usart 打印的功能: int _write(int file, char *ptr, int
我想定义一个记录器函数,比如 myPutStrLn = putStrLn . (++) "log: " main = do myPutStrLn "hello" 这很好。现在我想用 printf 格式
Printf module API详细介绍了类型转换标志,其中: %B: convert a boolean argument to the string true or false %b: conv
@H2CO3 这是我的主要代码: #pragma OPENCL EXTENSION cl_ amd_ printf : enable #define PROGRAM_FILE "matvec.cl"
Printf module API详细介绍了类型转换标志,其中: %B: convert a boolean argument to the string true or false %b: conv
您可以使用 printf 字段宽度说明符截断字符串: printf("%.5s", "abcdefgh"); > abcde 不幸的是,它不适用于数字(将 d 替换为 x 是相同的): printf(
关闭。此题需要details or clarity 。目前不接受答案。 想要改进这个问题吗?通过 editing this post 添加详细信息并澄清问题. 已关闭 4 年前。 Improve th
我遇到了我见过的最奇怪的错误之一。 我有一个简单的程序,可以打印多个整数数组。 对数组进行排序,然后打印...... place_in_buf(n100, 100); insertion(10
我的程序是每隔一段时间获取文件大小并显示它以记录任何更改。由于某种原因,执行下面的代码挂起,只为我提供了一个光标。没有打印或显示任何内容。 代码: #include #include #inclu
printf("It is currently %s's turn.\n", current->name); 我想知道为什么在 %s 之后打印出额外的换行符。我知道C 中的字符串总是以\0 结尾。没有
这个问题已经有答案了: printf anomaly after "fork()" (3 个回答) fork() in c using printf [duplicate] (2 个回答) 已关闭 9
我对编程很陌生。 我正在尝试编写一个程序,从数组中调用水果的价格。但我希望代码在写价格之前也写水果的名称。如果我键入 2,如何使输出为“Orange price : 10”而不仅仅是 price :
这个问题在这里已经有了答案: How do I print a non-null-terminated string using printf? (2 个答案) 关闭 7 年前。 例如,我有一个字符
我有一个 atmel UC3-L0 和罗盘传感器。现在我安装 AtmelStudio 并将一些演示代码下载到电路板中。但是我不知道演示代码中的函数 printf 会在哪里出现数据。我应该如何获取数据?
我有一个 atmel UC3-L0 和罗盘传感器。现在我安装 AtmelStudio 并将一些演示代码下载到电路板中。但是我不知道演示代码中的函数 printf 会在哪里出现数据。我应该如何获取数据?
嗨,我是 C 世界的新手,我的代码确实有些奇怪。目标是创建一个函数,可以在开头和结尾处用空格和/或制表符修剪字符串。我无法使用字符串库。 问题是我的代码中有一个 printf 只是用于测试,它的工作非
我是一名优秀的程序员,十分优秀!