My message got cut off for some reason. I was saying maybe setting the prompts (ps1, ps2) to empty strings would give the desired behavior.
sys.ps1 and sys.ps2 are documented at
https://docs.python.org/3.10/library/sys.html
James
My message got cut off for some reason. I was saying maybe setting the prompts (ps1, ps2) to empty strings would give the desired behavior.
sys.ps1 and sys.ps2 are documented at
https://docs.python.org/3.10/library/sys.html
James
Thanks. I want the thing the other way around though. If I have Python embedded into Prolog and Prologâs I/O redefined to use some window rather than file handles 0,1,2, I want Pythonâs I/O to use Prologâs. Well, that now works (be it a bit ugly to my taste) And yes, Windows doesnât get Unicode copy/paste > 0xffff to work very well. Works fine in Linux and MacOS âŚ
That would improve things a bit, but then we have no prompt left I now implemented this:
readline()
handler.That works flawlessly. The only small issue is that the Prolog command line history now captures both the Prolog and the Python commands if you use py_shell/0. Well, that also has it charm. This write hack smells a little fragile, but it surely is a step ahead. Tested in the Qt based swipl-win console. We automatically install this hack if Prolog I/O is not connected to the file handles 0,1,2. If Prolog uses 0,1,2, we do nothing.
We reached agreement on the Janus API in a Zoom call with the XSB developers last Friday. I have pushed changes that implement this. Summary
True
, False
and None
now map to @true
, @false
and @none
, where @
is a prefix operator. The notable advantage is that atoms are mapped unambiguously to Pythons strings in both directions.{k:v, ....}
, py({k:v, ...})
or as a SWI-Prolog dict. With a common API to access dicts in library(janus), this allows writing portable code that passes dicts to Python and handles dicts returned from Python in Prolog.janus-swi
and its module to janus_swipl
. This notably allows multiple versions for the various Prolog systems to coexist and avoids a conflict with the existing janus Python package.I think that with these changes the API is very close to stable. From now on we wonât make any changes that are likely to break compatibility and we will implement mechanisms to minimize the impact of incompatible changes.
The version currently on GIT has many fixes to Python object reference count handling. The library now passes testing using AddressSanitizer.
To make life really easy for the Python programmer, it would be great to be able to do
pip install swipl
to get a properly functioning version of SWI-Prolog. Does anyone know how to deal with installing large complex systems with many dependencies using pip? Can pip deal with cmake projects?
Hi All
I just want to say that v 1 of the Janus interface proved very powerful to many of us in leveraging applications. Weâve used it to access to vector stores, SpaCy, RDF, Elasticsearch, Wikidata and many other functionality with very little, if any, interface code per se. V. 2.0 which Jan has described on this message board is even more powerful and easy to use. I canât wait to see all the cool things that SWI developers come up with!
Theresa Swift
Installing on ubuntu 20.04 went without a hitch.
Installed to ~/sys using /usr/bin/python3.8.
Installed janus from git. This also installed OK.
Couple of gotchas with using janus though.
import janus
Traceback (most recent call last):
File ââ, line 1, in
ModuleNotFoundError: No module named âjanusâ
However,
import janus_swi
Worked fine.
janus_swi.once(âY is X+1â, {âXâ:1})
{âstatusâ: True, âYâ: 2}
Looking good so far.
janus_swi.once(âassertz(a(1))â)
{âstatusâ: True}
janus_swi.once(âassertz(a(2))â)
{âstatusâ: True}
Still good but then:
janus_swi.once(âforall(a(X), writeln(X))â)
1
2
Traceback (most recent call last):
File ââ, line 1, in
File â/home/eddie/.local/lib/python3.8/site-packages/janus_swi/janus.pyâ, line 130, in once
return swipl.call(query, inputs, keep)
I realised eventually I need to use _X rather than X. Obviously I need to understand the bindings malarky a bit better.
In general though, whenever there is an error that
NameError: name âjanusâ is not defined
message pops up.
It is definitely finding the right swipl binary.
Doing import janus_swi as janus doesnât change anything.
The features Iâve tested, once(), consult(), prolog() all work as expected itâs just the error messages that seem to get lost. Looking good though.
Hope to create a multi-threaded Python test app that calls out to Prolog soon.
(Edit: fixed output of forall() example).
Thanks for the evaluation!
That is how it should work. When embedding SWI-Prolog into Python the one and only module is janus_swi
, so we can have janus_xyz_prolog without conflicts. When Python is embedded into Prolog, both the modules janus
and janus_swi
are accessible as aliases. This all has pros and cons. Please suggest something better. Multiple Prolog systems implementing janus must be able to co-exist.
Thanks. There was an explicit reference to janus
that should have pointed at janus_swi
. Pushed a fix. And, indeed you need _X
as otherwise the query wants to succeed binding X
to a variable, which is not supported.
Looking forward. Things that can be added to the test suite are particularly welcome
That is how it should work. When embedding SWI-Prolog into Python the one and only module is janus_swi, so we can have janus_xyz_prolog without conflicts. When Python is embedded into Prolog, both the modules janus and janus_swi are accessible as aliases. This all has pros and cons. Please suggest something better. Multiple Prolog systems implementing janus must be able to co-exist.
Calling it janus_swi seems OK to me. I was just blindly copying the âfrom janus import *â from SWI-Prolog -- Calling Prolog from Python, possibly Iâm confused about the context of that page.
You can always do import janus as my_janus
.
This is considered to be bad style for large code bases (even with fancy IDEs because it can be difficult to statically resolve names due to Pythonâs dynamic nature); better to do import janus
and explicitly give the module name janus
when referencing imported classes or functions.
The Google style guide is based on years of experience and has reviewed by very good Python programmers, including some âcore developersâ - hereâs a link to the pros and cons of the various import options:
I was just blindly copying the âfrom janus import *â
This is considered to be bad style for large code bases (even with fancy IDEs because it can be difficult to statically resolve names due to Pythonâs dynamic nature); better to do import janus and explicitly give the module name janus when referencing imported classes or functions.
For sure, I was meaning just the name janus vs janus_swi, I could have made that clearer!
That doesnât solve the problem. Weâll be faced with the situation where both XSB and SWI-Prolog have an implementation of the Janus âstandardâ , but the implementation is independent. From the Python side, we now assume a package per Prolog system that is called
janus_*
, where the * identifies the Prolog system. If we do so, I can do
pip install janus_swi
pip insall janus_xsb
...
And next
import janus_swi as janus
and simply replace janus_swi with janus_xsb if I want to run the same code with XSB. Or not alias at all and chat to both Prolog systems from Python
I was just blindly copying the âfrom janus import *â from SWI-Prolog â Calling Prolog from Python, possibly Iâm confused about the context of that page.
Yes. The website is still documenting the situation before the changes that followed from the discussion with the XSB team. Will re-release shortly to get this all in sync.
marco@MacBookoBachini ~ % python
Python 3.11.4 (main, Jun 10 2023, 10:31:47) [Clang 13.0.0 (clang-1300.0.29.3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from janus_swi import *
>>> once("assertz(dog(fido))")
{'status': True}
>>> once("assertz(dog(elvis))")
{'status': True}
>>> once("assertz(cat(susie))")
{'status': True}
>>> once("assertz(cat(arturo))")
{'status': True}
>>> [a["Dog"] for a in Query("dog(Dog)")]
['fido', 'elvis']
>>> [a["Cat"] for a in Query("cat(Cat)")]
['susie', 'arturo']
>>> once("assertz(animal(_X) :- dog(_X))")
{'status': True}
>>> once("assertz(animal(_X) :- cat(_X))")
{'status': True}
>>> [a["Animal"] for a in Query("animal(Animal)")]
['fido', 'elvis', 'susie', 'arturo']
>>> once("retract(dog(fido))")
{'status': True}
>>> [a["Animal"] for a in Query("animal(Animal)")]
['elvis', 'susie', 'arturo']
Following the siteâs suggestions I have played a little bit with it today and it works writing the import directive in that way seemed the only way (as far as I could see, but maybe there are other waysâŚ) for not having to prefix janus_swi each time
>>> once("assertz(dog(fido))")
Great. You should not include data into your query string though. Only the âstructureâ, so you get
>>> once("assertz(dog(Dog))", {"Dog":"fido"})
Ok, for a test from the terminal your thing is ok of course, but if you do that with generated strings for the dogs youâll build up a large cache of queries and youâll get problems with dogs with complicated names with spaces, quotes, etc.
writing the import directive in that way seemed the only way (as far as I could see, but maybe there are other waysâŚ) for not having to prefix janus_swi each time
You can either import the specific function or import the module using an alias. The docs suggest
import janus_swi as janus
That will allow you to use the same program with XSB, simply by replacing janus_swi with janus_xsb.
Small detail - the build fails for -DCMAKE_BUILD_TYPE=Debug
(and probably for other build types):
-- Configuring SWI-Prolog-9.1.14
Trying to find debug version of Python
-- Could NOT find Python (missing: Python_EXECUTABLE Python_INCLUDE_DIRS Python_LIBRARIES Interpreter Development Development.Module Development.Embed) (Required is at least version "3.6")
Reason given by package:
Interpreter: Wrong ABI for the interpreter "/home/peter/.local/bin/python3"
You have to install the debug version of Python as well. Probably it should fall back to the nodebug version if it cannot find the debug version. Well, the debug build type is for developers only.