使用scrapy在C中嵌入Python时的Segfault

时间:2016-10-11 15:46:50

标签: python c scrapy embed

我目前正在尝试从C代码运行一些scrapy spider(在Python中),但我在测试时经常遇到段错误。

我有这个代码,允许我从c:

运行一个简单的python函数
    int main() {
    PyObject *retour, *module, *fonction, *arguments;
    char *resultat;

    Py_Initialize();
    PySys_SetPath(".");
    module = PyImport_ImportModule("test");
    fonction = PyObject_GetAttrString(module, "hellowrld);

    arguments = Py_BuildValue("(s)", "hello world");
    retour = PyEval_CallObject(fonction, arguments);
    PyArg_Parse(retour, "s", &resultat);
    printf("Resultat: %s\n", resultat);

    Py_Finalize();
    return 0;
}

如果我在test.py

中调用hellowrld函数,如下所示
def hellowrld(arg):
    return arg + '!!'

它可以正常工作,但我正在尝试从此代码运行runspider_with_url函数:

    # -*- coding: utf-8 -*-
import scrapy
from scrapy.crawler import CrawlerProcess
import lxml.etree
import lxml.html

class GetHtmlSpider(scrapy.Spider):
    name = "getHtml"
    def __init__(self, var_url=None, *args, **kwargs):
        super(GetHtmlSpider, self).__init__(*args, **kwargs)
        self.start_urls = [var_url]
    def parse(self,response):
        root = lxml.html.fromstring(response.body)
        print lxml.html.tostring(root)
def runspider_with_url(var_url):
    process = CrawlerProcess({
        'USER_AGENT': 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)'
    })
    process.crawl(GetHtmlSpider,var_url=var_url)
    process.start()
    return "It works!!"

当我尝试执行它时,我不断收到分段错误

我试图在我的python结束时添加它

foo = runspider_with_url("http://www.google.com/")
print foo

当我使用以下命令在bash中执行它时,此调用有效:

python -c 'import get_html; get_html.runspider_with_url("https://www.wikipedia.org")'

所以我可以让我的C程序用bash执行python,并将结果写成.txt,但我宁愿不这样做。

由于

1 个答案:

答案 0 :(得分:0)

PyArg_Parse(retour, "s", &resultat);存在段错误,因为脚本引发异常,retour为NULL。在将其包装到某些错误检测中之后,问题是PySys_SetPath(".");替换了现有的sys.path,因此无法再导入scrapy之类的内容。所以我通过快速调用插入sys.path的python代码来解决这个问题。在此过程中添加额外的错误处理,您将获得

#include <stdio.h>
#include <stdlib.h>
#include <Python.h>

int main() {
    PyObject *retour, *module, *fonction, *arguments;
    char *resultat;

    printf("starting\n");

    Py_Initialize();
    //PySys_SetPath(".");
    if(PyRun_SimpleString("import sys;sys.path.insert(0, '.')"))
    {
        printf("path expansion failed\n");
        return(2);
    }

    module = PyImport_ImportModule("test");
    if(module == NULL) {
        printf("import failed\n");
        PyErr_Print();
        return(2);
    }

    fonction = PyObject_GetAttrString(module, "runspider_with_url");
    if(fonction == NULL) {
        printf("could not find function\n");
        return(2);
    }

    arguments = Py_BuildValue("(s)", "hello world");
    if(arguments == NULL) {
        printf("arg parsing failed\n");
        return(2);
    }

    printf("Calling\n");
    retour = PyEval_CallObject(fonction, arguments);
    printf("Returned\n");

    // note: need to release arguments
    Py_DECREF(arguments);

    if(retour == NULL) {
        printf("It all went wrong\n");
        PyErr_Print();
        return(2);
    }

    PyArg_Parse(retour, "s", &resultat);
    printf("Resultat: %s\n", resultat);

    Py_Finalize();
    return 0;
}