[学习Cython编程]C中使用Python标准库(urllib,logging)
来源:互联网 发布:代发淘宝空包 编辑:程序博客网 时间:2024/06/03 14:33
Python的库非常丰富,如果能在C中使用Python的一些库,无疑是很让人兴奋的,下面我们就将在C中使用Pyhton的urllib模块和logging模块。
在C中调用Python需要包含整个Python的运行时库,链接模型如下:
在C/C++中嵌入Python代码是非常简单的,下面是代码模板:
#include <Python.h>int main(int argc,char** argv){ Py_SetProgramName(argv[0]); Py_Initialized(); /* Do all your stuff in side here... */ Py_Finalize(); return 0;}
注意“Pyhon.h"头文件需要首先被包含。
我们通过下面几个例子学习如何嵌入Python代码:
一:urllib
Python关于网络方面的库相当丰富,我们将在C中调用urllib.urlopen获取网页内容。
url.pyx文件:
import urllibcdef public char * open(char * url): content=urllib.urlopen(url).read() return contentpublic是Cython的关键字,代表这个函数被导出,所以Cython会自动创建url.c和url.h,url.h就是用来被C/C++代码包含的,Cython做的非常智能。
Python中的字符串对应的就是C中的char*,所以我们参数为char*,同时返回内容也为char*,Cython将自动帮我们完成类型转换。
我们来看看Cython自动产生的url.h头文件,我们将在主文件中包含它。
url.h文件:
#ifndef __PYX_HAVE__url#define __PYX_HAVE__url#ifndef __PYX_HAVE_API__url#ifndef __PYX_EXTERN_C #ifdef __cplusplus #define __PYX_EXTERN_C extern "C" #else #define __PYX_EXTERN_C extern #endif#endif__PYX_EXTERN_C DL_IMPORT(char) *open(char *);#endif /* !__PYX_HAVE_API__url */#if PY_MAJOR_VERSION < 3PyMODINIT_FUNC initurl(void);#elsePyMODINIT_FUNC PyInit_url(void);#endif#endif /* !__PYX_HAVE__url */这里面主要有两个函数,一个是我们用public关键字导出的open函数,另外一个在Python2平台上是initurl函数,这将初始化我们的模块。注意:”initurl"中的“url"就是我们的文件名,在Python中也就是模块。
下面我们将在C中调用open函数,代码为:
main.c文件:
#include <Python.h>#include "url.h"int main (int argc, char ** argv){ /* Boiler plate init Python */ Py_SetProgramName (argv [0]); Py_Initialize (); /* Init our url module into Python memory */ initurl(); if (argc >= 2) { /* call directly into our cython module */ printf("%s",open(argv[1])); } else printf ("require url...\n"); /* cleanup python before exit ... */ Py_Finalize (); return 0;}我们只是简单的在C中打印出open的获取结果,注意先调用初始模块函数,然后在调用模块中可用方法。
Makefile文件如下:
all:cython url.pyxgcc -g -O2 -fpic -c url.c -o url.o `python-config --includes`gcc -g -O2 -fpic -c main.c -o main.o `python-config --includes`gcc -g -O2 -o example main.o url.o `python-config --libs`clean:rm -f example url.c *.o我们看看运行结果:
很强大吧,有了Cython咱再也不怕C的标准库功能单一了。
认真看代码的童鞋对url.pyx可能会有疑惑,为什么不直接return呢,加个零时变量做啥,这是有原因的:
import urllibcdef public char * open(char * url): return urllib.urlopen(url).read()
如果url.pyx代码如上,编译产生错误:obtaining char* from temporary Python value
由于我们之间return将导致read()产生零时变量,当超出该函数作用域零时变量将被释放,导致我们返回的char*指针成为悬挂指针。
而当我们专门赋值为一变量时,将导致引用计数加一,变量生存周期也就在我们控制之下了。
二:logging
下面演示如何在C中使用Python的logging模块。
logger.pyx文件如下:
import loggingcdef public void initLogging (char * logfile): logging.basicConfig (filename = logfile, level = logging.DEBUG, format = '%(levelname)s %(asctime)s: %(message)s', datefmt = '%m/%d/%Y %I:%M:%S')cdef public void pyinfo (char * message): logging.info (message)cdef public void pydebug (char * message): logging.debug (message)cdef public void pyerror (char * message): logging.error (message)main.h头文件如下:
#ifndef __MAIN_H__#define __MAIN_H__#include <Python.h>#include <stdio.h>#include <stdarg.h>#define printflike \ __attribute__ ((format (printf, 3, 4)))extern void printflike cinfo (const char *, unsigned, const char *, ...);extern void printflike cdebug (const char *, unsigned, const char *, ...);extern void printflike cerror (const char *, unsigned, const char *, ...);#define info(...) \ cinfo (__FILE__, __LINE__, __VA_ARGS__)#define error(...) \ cerror (__FILE__, __LINE__, __VA_ARGS__)#define debug(...) \ cdebug (__FILE__, __LINE__, __VA_ARGS__)#include "logger.h"#endif //__MAIN_H__main.h头文件主要对man.c中函数的封装,自动传递文件名和行号。里面使用了变长参数,并且使用了GCC的__attrribute__特性。
#define printflike __attribute__ ((format (printf, 3, 4)))说明后面格式化字符串使用printf函数格式,并且变长参数从第三个参数开始,这更多的是让GCC可在编译阶段发现错误。
mian.c文件如下:
#include "main.h"void cinfo (const char * file, unsigned line, const char * fmt, ...){ char buffer [256]; va_list args; va_start (args, fmt); vsprintf (buffer, fmt, args); va_end (args); char buf [512]; snprintf (buf, sizeof (buf), "%s-%i -> %s", file, line, buffer); pyinfo (buf);}void cdebug (const char * file, unsigned line, const char * fmt, ...){ char buffer [256]; va_list args; va_start (args, fmt); vsprintf (buffer, fmt, args); va_end (args); char buf [512]; snprintf (buf, sizeof (buf), "%s-%i -> %s", file, line, buffer); pydebug (buf);}void cerror (const char * file, unsigned line, const char * fmt, ...){ char buffer [256]; va_list args; va_start (args, fmt); vsprintf (buffer, fmt, args); va_end (args); char buf [512]; snprintf (buf, sizeof (buf), "%s-%i -> %s", file, line, buffer); pyerror (buf);}int main (int argc, char ** argv){ /* Boiler plate init Python */ Py_SetProgramName (argv [0]); Py_Initialize (); /* Init our config module into Python memory */ initlogger (); if (argc >= 2) { /* call directly into our cython module parseConfig */ initLogging (argv [1]); info ("info message"); debug ("debug message"); error ("error message"); } else printf ("require path to output logfile...\n"); /* cleanup python before exit ... */ Py_Finalize (); return 0;}
我们来看看运行结果:
3 0
- [学习Cython编程]C中使用Python标准库(urllib,logging)
- Python标准库urllib
- Python 标准库 urllib
- python学习笔记(十四)标准库urllib
- python中urllib库简单使用
- python-urllib库学习
- python urllib库使用
- python标准库之logging
- [学习Cython编程]Cython编程入门
- python urllib urlretrieve学习使用
- 学习Python、Cython、PyCuda
- 使用Cython来保护Python代码库
- [学习cython编程] Cython Won't Bite
- Python 标准库 —— urllib/urllib2
- python标准库之urllib, httplib, urllib2
- Python常用标准库 --- urllib与urllib2
- python爬虫-urllib库学习
- Python学习之urllib库
- Struts2的interceptor实现权限管理
- DedeCMS_织梦_如何修改织梦内容页和列表页Pagelist分页样式?
- Java 泛型初识
- XDR-使用文件空间编码整数
- Mysql+java项目的中文处理
- [学习Cython编程]C中使用Python标准库(urllib,logging)
- 用java中System类的方法显示当前加载的系统属性
- uboot 与系统内核中MTD分区的关系
- 对象的串行化(Serialization)
- source insight ,eclipse, android studio常用快捷键
- VC8下多线程环境中AfxGetMainWnd()返回空指针问题及解决方法
- Cocoa框架是iOS应用程序的基础,了解Cocoa框架,对开发iOS应用有很大的帮助。 1、Cocoa是什么? Cocoa是OS X和 iOS操作系统的程序的运行环境。 是什么因素使一个程序成为Co
- 黑马程序员--内部类以及异常基础知识篇
- history.back(-1)和history.go(-1)的区别