2019独角兽企业重金招聘Python工程师标准>>>
Python Web Server Gateway Interface
python的wsgi接口,调用这个接口的主要原因在于要使用python作为动态网站的后端语言(c语言作为后端编写起来还是很慢的,除非是静态网站,静态网站纯c服务器也许会在后面继续研究),socket连接采用前一章写的c程序
python的wsgi接口参考:https://www.python.org/dev/peps/pep-3333/
python的c api接口参考:https://docs.python.org/2.7/c-api/
有了上面资料就开始这一章的编程了
首先后端采用python的django框架
django官网:https://www.djangoproject.com/
对于python使用pip安装即可,这里使用的是最新的1.8.4
from mysite import wsgi
def start_response(status, response_headers, exc_info=None):
print status
def HttpServer(method,path,req):
environ = {'REQUEST_METHOD':method,'SERVER_NAME':'BlogServer','QUERY_STRING':req,'SERVER_PORT':'80','PATH_INFO':path,'wsgi.input':''}
return wsgi.application(environ,start_response)
print HttpServer('GET','/admin/1/2','')#为了方便我们仅仅提取出三个接口,对于get方法,只有与请求链接与查询字符串两部分
这个文件保存在顶层mysite目录下,而不是mysite/mysite/目录下
由于我们请求一个不存在的链接所以会返回404状态码以及响应头和html正文
修改请求/admin/
302重定向
再修改成HttpServer('GET','/admin/login/','next=/admin/')
这次就是200正常响应了
根据上面python的wsgi接口的调用我们也知道该如果使用该接口,接下来就是用c语言来调用这个接口了
对于c调用python这部分内容在国内的网站极少描述,啃了好久官方的英文文档
#include
#include
static PyObject *start_response(PyObject *self, PyObject *args)//相当于上面python里面的start_response
{
printf("%s\n",PyString_AsString(PyObject_Str(PyTuple_GetItem(args, 0))));
printf("%s\n",PyString_AsString(PyObject_Str(PyTuple_GetItem(args, 1))));
return Py_None;
}
static struct PyMethodDef start_response_methods[] = {
//构建module使用,可能我还能吭透官方文档,所不能有直接回调的PyObject *构建方法
{"start_response", start_response, METH_VARARGS},
{NULL, NULL}};
int main()
{
Py_Initialize();//初始化
if (!Py_IsInitialized()) return -1;//是否正确初始化
PyRun_SimpleString("import sys");//导入sys
PyRun_SimpleString("sys.path.append('./')");//设置当前目录为工作目录
PyObject *pModule = PyImport_ImportModule("mysite.wsgi");//导入wsgi接口
if(!pModule){
printf("import failed!\n");//导入失败提示
return -1;
}
PyObject *pFunc = PyObject_GetAttrString(pModule, "application");//导入wsgi的调用
if(!pFunc){
printf("get function failed!\n");//失败提示
return -1;
}
PyObject *environ = PyDict_New();//构建python的字典类型
PyDict_SetItemString(environ, "REQUEST_METHOD", PyString_FromString("GET"));
PyDict_SetItemString(environ, "SERVER_NAME", PyString_FromString("BlogServer"));
PyDict_SetItemString(environ, "SERVER_PORT", PyString_FromString("80"));
PyDict_SetItemString(environ, "QUERY_STRING", PyString_FromString(""));
PyDict_SetItemString(environ, "PATH_INFO", PyString_FromString("/"));
PyDict_SetItemString(environ, "wsgi.input", PyString_FromString(""));
PyObject *module = Py_InitModule("start_response", start_response_methods);
PyObject *response = PyObject_GetAttrString(module, "start_response");//还要从module里获取回需要的回调方法(也许有更好的办法)
PyObject *pArgs = PyTuple_New(2);//构建元组类型,传参使用
PyTuple_SetItem(pArgs, 0, environ);
PyTuple_SetItem(pArgs, 1, response);
PyObject *res = PyObject_CallObject(pFunc, pArgs);
printf("%s",PyString_AsString(PyObject_Str(res)));//打印结果
//把指针都回收销毁掉
Py_DECREF(res);
Py_DECREF(pArgs);
Py_DECREF(response);
Py_DECREF(environ);
Py_DECREF(pModule);
Py_DECREF(pFunc);
Py_Finalize();
Py_DECREF(module);
return 0;
}
python2.7编译一下
编译运行一下
PyObject其实就是python中的变量名,却没有固定的一个数据类型,在c语言中也是这么体现的,感觉有点特别,等下一部分将会合并前面多线程socket编程,构成一个正常的服务器