Hello,
My new year main resolution: stop keeping my side-projects for me. It’s been like 1 year that I created these two projects, one coming from a refactoring of the other. Now it is time to take time to announce them. I initially come from Python world and during my bachelor & master, I really liked to use matplotlib to plot data using Python. So I wanted to be able to use this Python module from Pharo. I did it by generating Python 3 code from Pharo and making Python 3 executing it. So, first I implemented everything in MatplotLibBridge package and then I split it in two package in order to be able to eventually create bridges to other Python 3 modules. So, Python3Generator [1] is made for generating programatically Python 3 code from Pharo. Basically, it allows you to easily build a Python 3 AST, to serialize it in Python 3 source code and eventually to execute it. For now you can transfer data from Pharo to Python (e.g. providing arguments to functions that are Pharo’s objects) but you can not retrieve data stored in Python variable from Pharo (but it should be possible, just I don’t need to do that for my bridge to matplotlib). Some examples are provided on the github’s README. MatplotLibBridge [2] is made for creating plots using matplotlib [3] from Pharo. There is a bunch of examples of what you can do on the README. The two features from matplotlib I like the most are: 1. You can generate your plot in a lot of file formats (png, pdf, svg, ps, etc…) 2. It allows to embed LaTeX mathematical formulae everywhere in the plot (which can be really cool). All the possible plots in matplotlib are not available in Pharo’s side because I build parts of the bridge when I need them but it is not hard to do. I someone is interested in a plot type not available yet, please tell me. So, it is announced, if someone want to do something with those, please do it! Happy new year. Regards, Julien --- Julien Delplanque Doctorant à l’Université de Lille 1 http://juliendelplanque.be/phd.html Equipe Rmod, Inria Bâtiment B 40, avenue Halley 59650 Villeneuve d'Ascq Numéro de téléphone: +333 59 35 86 40
|
Administrator
|
Julien wrote
> My new year main resolution: stop keeping my side-projects for me. Great! Keep them coming… ----- Cheers, Sean -- Sent from: http://forum.world.st/Pharo-Smalltalk-Users-f1310670.html
Cheers,
Sean |
In reply to this post by Julien Delplanque-2
Good. Really nice to see more bridges between Pharo and the
external world and playing well with other programming languages,
frameworks and documentation systems. Cheers, Offray On 01/01/18 14:22, Julien wrote:
Hello, |
In reply to this post by Julien Delplanque-2
On Mon, Jan 1, 2018 at 8:22 PM, Julien <[hidden email]> wrote:
> Hello, > > My new year main resolution: stop keeping my side-projects for me. I ***LOVE IT*** Last year I took as decision, release all the books that I had half finished :) and I ended up creating the booklets to flush my hardisc. Stef > > It’s been like 1 year that I created these two projects, one coming from a > refactoring of the other. > Now it is time to take time to announce them. > > I initially come from Python world and during my bachelor & master, I really > liked to use matplotlib to plot data using Python. > > So I wanted to be able to use this Python module from Pharo. I did it by > generating Python 3 code from Pharo and making Python 3 executing it. So, > first I implemented everything in MatplotLibBridge package and then I split > it in two package in order to be able to eventually create bridges to other > Python 3 modules. > > So, Python3Generator [1] is made for generating programatically Python 3 > code from Pharo. Basically, it allows you to easily build a Python 3 AST, > to serialize it in Python 3 source code and eventually to execute it. For > now you can transfer data from Pharo to Python (e.g. providing arguments to > functions that are Pharo’s objects) but you can not retrieve data stored in > Python variable from Pharo (but it should be possible, just I don’t need to > do that for my bridge to matplotlib). Some examples are provided on the > github’s README. > > MatplotLibBridge [2] is made for creating plots using matplotlib [3] from > Pharo. There is a bunch of examples of what you can do on the README. The > two features from matplotlib I like the most are: 1. You can generate your > plot in a lot of file formats (png, pdf, svg, ps, etc…) 2. It allows to > embed LaTeX mathematical formulae everywhere in the plot (which can be > really cool). All the possible plots in matplotlib are not available in > Pharo’s side because I build parts of the bridge when I need them but it is > not hard to do. I someone is interested in a plot type not available yet, > please tell me. > > So, it is announced, if someone want to do something with those, please do > it! > > Happy new year. > > Regards, > > Julien > > [1]: https://github.com/juliendelplanque/Python3Generator > [2]: https://github.com/juliendelplanque/MatplotLibBridge > [3]: https://matplotlib.org > > --- > Julien Delplanque > Doctorant à l’Université de Lille 1 > http://juliendelplanque.be/phd.html > Equipe Rmod, Inria > Bâtiment B 40, avenue Halley 59650 Villeneuve d'Ascq > Numéro de téléphone: +333 59 35 86 40 > |
did you use a socket to communicate from Pharo to Python? it does not sound like it it sounds more one way i am interested in using sockets to communicate between programs but i haven't done much with it yet maybe you can include sockets in your generated Python to talk back to Pharo ? i got Dolphin Smalltalk to talk to Pharo using a socket but i kind of forgot about it did you look at Roassal ? Roassal does a lot of plotting they look very nice they have mouse interactions and lots of cool stuff but i don't know how they relate to other plotting programs i imagine that Roassal tries to do things not done in other programs but i don't really know i looked at some other plotting thing also can't remember Sci something Roassal has a nice declarative style that is nice i want to use it a lot in future i use Roassal in the Moose Pharo image because it is pre installed i have a rich text tree editing program in Dolphin Smalltalk that i use like a note taking program like everNote but as a great big tree using the old Windows tree widget in Dolphin 6 which i like and i store a lot of my text stuff in there and i would like to store and edit Racket programs or lisp programs in there in a tree format and your project sounds interesting about how to maybe generate Racket code that will allow me to use Dolphin and Pharo and other Smalltalks as a front end to Racket or commonLisp etc because i don't like the GUIs or IDEs of those things ( they're so primative )( but i don't know them well )( they just look brittle )( and C like ) and i believe there is a command line interface in Pharo so you can execute external programs like generated scripts On Tue, Jan 2, 2018 at 12:30 PM, Stephane Ducasse <[hidden email]> wrote: On Mon, Jan 1, 2018 at 8:22 PM, Julien <[hidden email]> wrote: |
There is a concept of « Interpreter » in this framework. Basically, an interpreter is an object to which you provide strings containing Python 3 code and that execute it. There is a FFI interpreter which writes the python code in a file on the file system and uses the int system(char *) function to make python execute the file. It also redirect stderr to a file and read that file after execution in order to have eventual execution errors. There is a Atlas interpreter which uses the Atlas project from Kilon. Atlas makes Python and Pharo talk trough sockets. So this is what you want I guess. The thing is, if I want to send data from Python Pharo, I would use the Atlas interpreter and serialise data to send to Pharo through a socket as JSON for example. But for Matplotlib I do not need to read Python’s value so I did not implemented that. Nevertheless, it could be cool to have this ability to get Python’s data in Pharo because we could use Numpy or others Python modules for which getting Python's is important. Another interesting thing when communicating through sockets between two different languages is: How do you manage callbacks? For example I would like to be able to make Python execute a Pharo Block at a certain point of the execution or to make Pharo execute a Python’s lambda. I do not have answer for that.
Yes I know Roassal and I think this is a great project when you want to do interactive visualisations and keep them inside the image. But, as far as I know, when it comes to export the plot into a pdf file to have a nice integration in a LaTeX document, you can not do that in Roassal. Of course you can export your plot as svg but then you have to deal with integrating svg inside LaTeX… Furthermore, as I said before, I already used MatplotLib in Python and really liked its simple interface… Finally, at the beginning it was just an experiment for fun, but then I saw it was quite easy to interface to a Python library from which you don’t need to get values back in Pharo so I continued this project and used it when I had to plot stuff. Now I think it is quite usable and I enhance it a little every time I use it and see there is a part of the bridge I need that is not built yet. :-)
Julien --- Julien Delplanque Doctorant à l’Université de Lille 1 http://juliendelplanque.be/phd.html Equipe Rmod, Inria Bâtiment B 40, avenue Halley 59650 Villeneuve d'Ascq Numéro de téléphone: +333 59 35 86 40 |
Well done, great to see my code be reused for new project. I am happy to see people take it one step further. What exactly your code offers additional to my code ? Is there is something special you do with it?
You don't really need this approach. The reason why I did not add this feature in Atlas is because the way that Python import its files is basically normal execution. So each time you import mymodule what you do is you execute mymodule. Basically Python does the same thing with execution when it does a import. This is why we need the if main thing to detect whether the module execution happened because of import or because it was executed directly (via terminal, or double click). So in case of Atlas all you have to do is put your code in a python module and import then module from atlas with sendMessage: 'import mymodule'.
Atlas provide this ability via getValue: message. There is a catch , what you get is always strings. So that means if you use a complex Python object you will have to convert that to some form of string format that clearly represents the data . JSON could be a good candidate here because both Python and Pharo support this. I have created a very basic template Pharo object that parses strings to Pharo objects as an example that I have included but still its going to be tricky especially with Numpy because it all happens at C level and not Python level for performance reasons. Still its not that hard to do if you really need this feature which in your case you don't.
You can do that in Pharo side or Python side , its up to you. Only you need is a string that acts as a single. For example getValue: technically is kinda like a callback because it sends the string containing the python command but it waits for response from Python that will signal it if the return string contains the signature, if I remember correctly, getvalue: value. So essentially what I have done is create a mini transfer protocol. It was necessary for me to do this not because of callback per se, but because I wanted to retain the live coding abilities of Pharo while coding using Python libraries. In order to do that I wanted to send Python errors back to Pharo and trigger the Pharo debugger with the python error as the name of the error. To do that I had to implement a protocol that diffirentiate between return values and value that concern only Atlas in this case python errors. This protocol can be extended of course to contain a myriad of things, callbacks, thread synchronization, C function calls , C memory etc. So technically speaking its already possible through Atlas. If you want to do something very special with callback that involves the Pharo IDE as I did with Python error you only need to extend this protocol adding your own kind of signal strings.
As far as my Atlas is concerned I had made also a Python 2 version but never bothered to continue developing it because I needed only Python 3. The good news is Python 2 and 3 have minor differences when it comes to sockets. Indeed Atlas wont work magically with other language but porting it is not hard because I tried to keep the majority of the code as much as I could in Pharo side for this precise reason. So my initial intention was to provide Atlas to Pharo community as a means to use libraries of any programming language from inside Pharo. I hoped that people would use it as the foundation to bring other languages inside Pharo like I did for Python but alas it seems Pharoers for some weird reason prefer to use Pharo :D (joke for those that did not notice the laughing smiley face) I was also planning adding the ability of memory mapped files that I used in my CPPBridge prohect. This form of communication accelerate things by thousands of times because its low level. But it sacrifices remote execution which means in this case you fall back to the existing socket bridge approach. This was necessary at the time because sockets are not a good idea if you plan on doing large loops, because obviously there is a delays , its low around 1 millisecond and less depending on the power of CPU but if you do 1 million iterations would turn that 1 millisecond to 1000 seconds which of course is no fun. On the other hand even without memory mapped files you can avoid this by making sure you keep the loop either on python side or pharo side with the condition it does not contain Atlas communication commands that open and close the socket. |
Python3Generator allows to generate a Python 3 AST programatically. So basically you have objects that represent Python 3 AST nodes and some messages in top of that to make the generation of the AST easier from Pharo. E.g. ast := 'print' asP3GIdentifier callWith: #('Hello world'). ast inspect If you have a look at the readme on GitHub you will see more complexe examples.
I wanted that to avoid the user having to set up a Python server listening on a socket when it is not needed to get data from Python.
Yep, but if I want to get value from Python into Pharo, I want to have them as Pharo objects so as you said some conversion has to be made which means more work.
|
yes buy why ? Why you want to generate objects , Python AST nodes are already python objects and you already generate AST nodes each time you execute python code. Using the Atlas syntax your above example would be simpler py = ATLPyParser new py print:'("Hello World")' Is there an advantage using your own syntax ? Is there any advantage of direct access to Python AST?
Yes I did take a look but I still did not know why you bother generating identifiers for each python command manually when ATLPyParser does this automatically for you. For example you have this example
Using the ATLPyParser of Atlas would have been much simpler py = ATLPyParser Atlas sendMessage:'import json,os' py file:'= open("/tmp/osp3.json","w")';e; file write:'(json.dump({"os":os.name,"uname":os.uname}))';e; file close;e. Or the point is to fully parse pharo syntax to python ?
Actually the server is setup at Pharo side, Python side is merely a client. All the heavy lifting is taking place via Pharo. The user does not need to do anything , its automatic. But yeah if you want to completely liberate yourself from sockets I can understand that, though I do not understand why, you use sockets every time you access the internet and they are really fast. So its not as if you can avoid socket generation. |
In MatplotLibBridge I do some checking/optimisations on the AST generated by high-level API objects (e.g. for optimisation avoid importing a package twice). With an AST it is easy with basic Atlas I think this is not possible. Having an AST allow to do stuff on the code to execute before executing it and this easily and maintainable (i.e. not using regexes).
What I would like to experiment for fun is translating Pharo Smalltalk to Python 3. And as said before with your technique you can not modify the AST easily before sending it to Python.
I agree that sockets are not costly but a problem I see with them is that it creates a *huge* security issue by letting anyone execute arbitrary Python code from the outside (except if you configured atlas to only accept connections from 127.0.0.1). Since I do not need socket to execute arbitrary code I prefer not using them. |
Ah ok so you want to target the AST specifically, I see now. Yeap I did not implement any security measure for Atlas because the goal was local and not remote execution. Yes indeed the socket connects directly to 127.0.0 port 4000.So Atlas is preconfigured to work locally. I think safety is something that the developer must control to make it specific to the nature of the code. Plus I am no web dev. Plus if OS security is breached to gain access to Atlas, the user is already in a deep mess, Atlas will be the least of his concerns. If my assumption is correct and you execute python code by writing it to a python file and then executing the module, note that this approach is actually much slower to the socket approach. Which is why I did not go for it in the first place. Sockets work similar to files but use memory and thus do not write to hard disk and so they work faster. Which is why sockets are so popular for local IPC as well. I am not sure if Pipes as faster but I doubt it. Memory mapped files are much safer and much faster, which is why shared memory is the most popular IPC for local comunication , the hacker would have to hack the memory low level style because memory mapped files are controlled by the OS kernel and is basically what is used for shared libraries, the very popular DLLs on windows , dylib on MacOS, and so on Linux. If performance becomes a serious issue for you and you want the safest way to do local IPC , I highly recommend this approach. But if you are happy with your current solution, there is no need to modify your code. On Fri, Jan 5, 2018 at 9:09 PM Julien <[hidden email]> wrote:
|
In reply to this post by Julien Delplanque-2
I have just tried Python3Generator. Impressive work! It is a wonderful contribution!
Cheers, Alexandre > So, Python3Generator [1] is made for generating programatically Python 3 code from Pharo. Basically, it allows you to easily build a Python 3 AST, to serialize it in Python 3 source code and eventually to execute it. For now you can transfer data from Pharo to Python (e.g. providing arguments to functions that are Pharo’s objects) but you can not retrieve data stored in Python variable from Pharo (but it should be possible, just I don’t need to do that for my bridge to matplotlib). Some examples are provided on the github’s README. > |
Happy you find this interesting.
If you have suggestions, just let me know by creating an issue on the repository. If you create bridges to some Python 3 libraries, tell me as well! :-) Julien
--- Julien Delplanque Doctorant à l’Université de Lille 1 http://juliendelplanque.be/phd.html Equipe Rmod, Inria Bâtiment B 40, avenue Halley 59650 Villeneuve d'Ascq Numéro de téléphone: +333 59 35 86 40
|
AI Python libraries may be my first target….
I will let you know Alexandre
--
_,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;: Alexandre Bergel http://www.bergel.eu ^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;.
|
Beware that no mechanism to get back values from Python is defined for now (except if you just want the String
representation of those objects, then you can get that if you use atlas).
I’d like to have that but it is not easy. I would like a way to describe how to map Python’s objects to Pharo’s objects from Pharo and to have the code to do that in Python side generated automatically but some thinking is needed… Julien --- Julien Delplanque Doctorant à l’Université de Lille 1 http://juliendelplanque.be/phd.html Equipe Rmod, Inria Bâtiment B 40, avenue Halley 59650 Villeneuve d'Ascq Numéro de téléphone: +333 59 35 86 40
|
In reply to this post by Julien Delplanque-2
Thank you Julien for this very interesting piece of code. What I need at the moment is a way to transform semi-automatically Numpy code to PolyMath code ... On Mon, Jan 1, 2018 at 8:22 PM, Julien <[hidden email]> wrote:
-- Serge Stinckwich UMI UMMISCO 209 (IRD/UPMC/UY1)
|
Hello Serge,
Do you mean pieces of code you wrote in Python using Numpy that you want to transform to Smalltalk code using PolyMath? It’s kind of the other way around of this project. :-) Julien --- Julien Delplanque Doctorant à l’Université de Lille 1 http://juliendelplanque.be/phd.html Equipe Rmod, Inria Bâtiment B 40, avenue Halley 59650 Villeneuve d'Ascq Numéro de téléphone: +333 59 35 86 40
|
On Wed, Jan 10, 2018 at 2:23 PM, Julien <[hidden email]> wrote:
yes this is exactly the opposite :-( I guess I need a Python parser and after that I can do AST transformation ... Or using regex I can do basic stuff ... -- Serge Stinckwich UMI UMMISCO 209 (IRD/UPMC/UY1)
|
I guess the hardest part will be to define the 1 - 1 mapping between Numpy and PolyMath APIs, no?
I mean, how can you ensure that features using Floats will behave exactly the same in Python and Smalltalk for example? Julien
--- Julien Delplanque Doctorant à l’Université de Lille 1 http://juliendelplanque.be/phd.html Equipe Rmod, Inria Bâtiment B 40, avenue Halley 59650 Villeneuve d'Ascq Numéro de téléphone: +333 59 35 86 40
|
In reply to this post by SergeStinckwich
2018-01-10 14:26 GMT+01:00 Serge Stinckwich <[hidden email]>:
Hi Serge, there is a Python2.7 parser with AST that could be used. Thierry
|
Free forum by Nabble | Edit this page |