Problem with SWI-PROLOG and DJANGO

779 views
Skip to first unread message

Fred

unread,
Jan 23, 2015, 5:22:58 PM1/23/15
to
Hi everybody,

I want to work with Python and SWI-Prolog. I've tried a snippet in Python with the module pyswip and it's works quite good :
from pyswip import Prolog

   
def onTest(self):
        prolog
= Prolog()
        temp
= 'test.prolog'
        prolog
.consult(temp)
        results
= list(prolog.query("father(michael,X)"))
        X
= results[0]['X']
        prolog
= None
       
print X
.
Then I've tried to use quasi the same code in Django but I've got an exception
The code in views.py :
from pyswip import Prolog

def onTest(request):
    prolog
= Prolog()
    temp
= 'test.prolog'
    prolog
.consult(temp)
    results
= list(prolog.query("father(michael,X)"))
    X
= results[0]['X']
    prolog
= None
   
print X
   
return HttpResponse(X)

 
the code of 'test.prolog' :
father(michael,john).
father
(michael,gina).

error in the browser :

WindowsError at /planning/onTest/

exception: access violation reading 0x00000020
Request Method:GET
Request URL:http://localhost:8000/planning/onTest/
Django Version:1.7.3
Exception Type:WindowsError
Exception Value:
exception: access violation reading 0x00000020
Exception Location:C:\Python27\lib\site-packages\pyswip\prolog.py in __call__, line 94
Python Executable:C:\Python27\python.exe
Python Version:2.7.8

and the message in the console :
Exception AttributeError: 'swipl_qid' in <bound method _QueryWrapper.__del__ of <pyswip.prolog._QueryWrapper object at 0x037AB7D8>> ignored

I've tried to debug and I've found that the code never execute the line :
            self.swipl_fid = PL_open_foreign_frame()

I've tried to read the docs about
PL_open_foreign_frame()
but I don't really understand what the problem may be.
Anyone can help me to understand and ... solve my problem
Thanks
Fred

Fernando Bautista

unread,
Apr 20, 2015, 11:43:56 AM4/20/15
to swi-p...@googlegroups.com
Hi Fred, I have the similar problem, when I execute my view for second time, terminal show : Segmentation fault (core dumped) , you could fix the problem?

Sincerely
Fernando

Dane Miller

unread,
Dec 12, 2015, 10:48:48 PM12/12/15
to SWI-Prolog
Hey Fred, I got the same error. Did you eventually find a solution? It would be a big help. :)

Jan Wielemaker

unread,
Dec 13, 2015, 5:12:10 AM12/13/15
to Dane Miller, SWI-Prolog
Hi Dane,

I know little about Python nor Dango. My first suspicion would be that
it is thread-related. Does Django use threads? I'm also not sure about
`prolog=Prolog()`. I don't know how that matches to SWI-Prolog's C API.
The way it works though is that a process can only create one Prolog
system using PL_initialise(), which typically stays there the remainder
of the life of the process. Cleanup (PL_cleanup() is at best incomplete.
After initializing it, it may be used in the thread that initialized it.
You must make sure this thread never dies (i.e., you typically use the
process main thread). If you want to use it from a different thread you
need to attach a new Prolog engine to the thread.

I fear this isn't really an answer. It may help you and/or the developer
of the pyswi interface to sort out what happens.

Cheers --- Jan
> returnHttpResponse(X)
>
> |
>
> the code of 'test.prolog' :
> |
> father(michael,john).
> father(michael,gina).
> |
>
> error in the browser :
> |
>
>
> WindowsErrorat /planning/onTest/
>
> exception:access violation reading 0x00000020
>
> RequestMethod: GET
> RequestURL: http://localhost:8000/planning/onTest/
> Django Version: 1.7.3
> Exception Type: WindowsError
> Exception Value:
>
> exception: access violation reading 0x00000020
>
> Exception Location: C:\Python27\lib\site-packages\pyswip\prolog.py
> in __call__, line 94
> Python Executable: C:\Python27\python.exe
> Python Version: 2.7.8
>
>
> |
> and the message in the console :
> |
> ExceptionAttributeError:'swipl_qid'in<bound method
> _QueryWrapper.__del__ of <pyswip.prolog._QueryWrapper objectat
> 0x037AB7D8>>ignored
> |
>
> I've tried to debug and I've found that the code never execute the
> line :
> |
> self.swipl_fid =PL_open_foreign_frame()
>
> |
> I've tried to read the docs about
> |
> |PL_open_foreign_frame()
> |
> |
> but I don't really understand what the problem may be.
> Anyone can help me to understand and ... solve my problem
> Thanks
> Fred
>
> --
> You received this message because you are subscribed to the Google
> Groups "SWI-Prolog" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to swi-prolog+...@googlegroups.com
> <mailto:swi-prolog+...@googlegroups.com>.
> Visit this group at https://groups.google.com/group/swi-prolog.
> For more options, visit https://groups.google.com/d/optout.

Michael BEN YOSEF

unread,
Dec 13, 2015, 6:52:50 AM12/13/15
to SWI-Prolog, dane.mi...@gmail.com
Indeed, PySWIP is not thread-safe. If you want to use multiple instances concurrently, you can use Python's multiprocessing module and run each PySWIP in a separate process.

One approach I've found to work well with Django is to use a multiprocessing.Pool of worker subprocesses. Each call to a Django view will use an available PySWIP/SWI-Prolog instance to run Prolog code and won't block other views. Here is a skeleton:

from multiprocessing import Pool

def process(data):
   
return pool.apply(dowork, (data,))

# initialise is called by each of the newly spawned subprocesses. Since
# "from pyswip import Prolog" already loads SWI-Prolog, we have to put
# it inside this function for each process to have its own instance.
# Each process stores its Prolog instance in it's own global variable
# called "prolog".
#
def initialise():
   
global prolog
   
from pyswip import Prolog
    prolog
= Prolog()
    prolog
.consult(a_prolog_load_file)

# dowork is called on an available subprocess by Pool.apply. It picks
# up its Prolog instance in its own private "prolog" global variable.
#
def dowork(data):
   
global prolog

   
# Use PySWIP to process data
    prolog
.query(...)

# N.B.: The Pool itself must only be created once all the functions
# needed by the subprocesses have been defined, because the call to
# Pool() "magically" wraps up the current environment to pass on to the
# forked subprocesses.
pool
= Pool(None, initialise)
# 'None' means initialise cpu_count() many of them.


Importing this module will start the PySWIP/SWI-Prolog subprocesses and calling process(data) will pass data to an available subprocess (and return the result) each time.

Another tip: I have had better success with the pyswip_alt PyPI package, which contains a few bugfixes on top of the original pyswip package.

Hope that helps!

Michael
Reply all
Reply to author
Forward
0 new messages