2016-10-11 6 views
0

Я сейчас пытаюсь запустить некоторый scrapy spider (в Python) из кода C, но я постоянно получаю segfault во время тестирования.Segfault при вложении Python с использованием scrapy в C

у меня есть этот код, который позволит мне выполнить простую функцию питона из C:

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; 
} 

если я вызвать функцию hellowrld, которая выглядит, как это в test.py

def hellowrld(arg): 
    return arg + '!!' 

это будет работаю нормально, но я пытаюсь запустить функцию runpider_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!!" 

И w курица я пытаюсь выполнить его, я постоянно получаю ошибки ошибки сегментации

Я попытался добавить это в конце моего питона

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

Этот вызов работает, когда я выполнить его в Баш с помощью следующей команды:

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

Так что я мог бы попросить мою C программу для выполнения питона с Баш и writte результата в .txt, но я предпочел бы не так.

Благодаря

+0

Вы не проверяете значения возврата, особенно 'PyArg_Parse'. Предположим, что она не вернула строку. – tdelaney

ответ

0

Существует выдаёт ошибку сегментации в PyArg_Parse(retour, "s", &resultat);, потому что сценарий вызывает исключение и retour является NULL. После обертывания, что при некотором обнаружении ошибок проблема заключалась в том, что PySys_SetPath("."); заменяет существующие sys.path, поэтому такие вещи, как scrapy, больше не могут быть импортированы. Поэтому я исправил это с быстрым вызовом кода python, который вставляет в sys.path. Добавляя дополнительную обработку ошибок в пути, вы получаете

#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; 
} 
+0

Привет, спасибо, это решило мою проблему. Теперь я хотел бы вернуть результат функции синтаксиса в код C вместо его печати. Я попытался использовать какую-то глобальную переменную, которая используется вместо печати, и возвращается в функции runpider. Но кажется, что тот, который я изменяю в своем классе, не совпадает с тем, который я хочу вернуть. –

+0

Интересно. Я не знаю много о 'scrapy', но если ваш синтаксический анализатор выводит результаты, скажем,' self.foo', тогда вы можете вернуть 'process.foo', и он будет в C-коде' 'retour'. Если это не сработает ... тогда у вас есть еще один вопрос! – tdelaney

+0

После нескольких исследований я обнаружил, что мне нужно было создать класс, который наследует Item подобно классу foo (Item) с этим заголовком «from scrapy.item import Item, Field» –