Can I use Python code and libraries in Racket? I have installed PyonR (https://github.com/pedropramos/PyonR) in DrRacket so I can choose "#lang python" and run Python code. But how can I combine Racket and Python language codes for my application?
There is also a limited Python to Lisp translator at https://github.com/nurv/pnil . Is there something similar for Racket?
Edit: As advised in comments, I tried following. This python code in file "pysamples.rkt" works well in DrRacket:
#lang python
def greet(name):
print 'Hello', name
greet('Alfred')
Output:
Hello Alfred
I tried using above definition in Racket code, but it did not work. Following is the Racket code:
#lang racket
; (require python/config) (enable-cpyimport!) ; ran this once; worked.
(#%require "pysamples.rkt")
(greet "Racket_code")
The error is:
greet: unbound identifier in module in: greet
The PyonR project is the closest ready-to-use way of using Python libraries from Racket that I know of. However note that there is a difference between Python libraries written in Python and Python libraries that are a thin Python layer on top of a C library. As you have experienced the latter type is not working (to my knowledge at least - but Pedro is the one to ask).
If you need to use a library written in language X (for X could be Python) you can always write a "listener" program in language X that waits for messages from a Racket program, and when a message is received, computes an answer and sends it back to the Racket program. How to send and receive messages is up to you, but a simple option is to have two files, one "R-to-X" which Racket writes to and X reads from, and another "X-to-R" where Racket receives the messages.
This approach has some overhead, but if the computation takes longer than sending the message, then it is a viable solution.
Accoring to the readme you can import python 2.7 packages, but you need to use cpyimport. One of the examples looks like this:
#lang python
cpyimport numpy as np
from "racket" import time
def add_arrays(n):
result = np.zeros((100,100))
for i in range(n):
result += np.random.randint(0, 100000, (100,100))
return result
print time(add_arrays(10000))
Looking at the code, a pure python library you could just import give that it's in rackets paths and was given #lang python top line. all defined are always exported.
The previous answers and comments addressed difficulties with certain Python libraries, but if you're just interested in using a function from a pure Python file in a Racket module, try something like this:
In file "greetings.py":
#lang python
def greet(name):
print 'Hello', name
In Racket:
#lang racket
(require python)
(py-import "greetings" as python-module)
(py-method-call python-module "greet" "Racket")
Related
I'm using pyinstaller to distribute my code as executable within my team as most of them are not coding/scripting people and do not have Python Interpreter installed.
For some advanced usage of my tool, I want to make it possible for the user to implement a small custom function to adjust functionality slightly (for the few experienced people). Hence I want to let them input a python file which defines a function with a fixed name and a string as return.
Is that possible?
I mean the py-file could be drag/dropped for example, and I'd tell them that their user-defined function needs to have a certain name, e.g. "analyze()" - is it now possible to import that from the drag/dropped pythonfile within my PyInstaller Script and use it as this?
I know, it certainly will not be safe/secure and they could do evil things, delete files and so one... But that are things which we don#t care at this point, please no discussions about it. Thanks!
To answer my own question: yes it does actually work to import a module/function from a given path/pythonfile at runtime (that I knew already) even in PyInstaller (that was new for me).
I used this for my Py2.7 program:
f = r'C:\path\to\userdefined\filewithfunction.py'
if os.path.exists(f):
import imp
userdefined = imp.load_source('', f) # Only Python 2.x, for 3.x see: https://stackoverflow.com/a/67692/701049
print userdefined # just a debugging print
userdefined.imported() # here you should use try/catch; or check whether the function with the desired name really exists in the object "userdefined". This is only a small demo as example how to import, so didnt do it here.
filewithfunction.py:
--------------------
def imported():
print 'yes it worked :-)'
As written in the comments of the example code, you'll need a slightly different approach in Python 3.x. See this link: https://stackoverflow.com/a/67692/701049
I'm really new to python and I have made the following program:
class AddressBook:
def __init__(self):
self.b = {}
def insert(self,name, phone):
self.b[name]=phone
print "I am confused"
def get(self,name):
return self.b[name]
def has_name(self,name):
return self.b.has_key(name)
def list(self):
for n,p in self.b.iteritems():
print n,p
def delete(self, name):
del self.b[name]
def orderedList(self):
orderedkeys = self.b.keys()
orderedkeys.sort()
for n in orderedkeys:
print n, self.b[n]
I now want to compile it test it out in terminal to see if it all works.
I went to the directory and compiled it with
python address.py
Now I want to add things to the list, print the contents of the list, delete them (pretty much play around with my program) but I don't know how...
After compiling, how do I manually test (play around) with my python program?
Thanks in advance.
Python is an interpreted language, and .py files do not require direct compilation. There are a few ways to run Python code, but for "playing around" you can simply activate the Python interpreter and import the class.
In a command prompt:
> python
In Python:
>>> from address import AddressBook
>>> a = Addressbook()
>>> a.insert("Jenny", "867-5309")
>>> a.get("Jenny")
'867-5309'
The python script is not compiled. At least not in ways as other languages, like Fortran and C. From this answer:
Python has a compiler! You just don't notice it because it runs automatically. You can tell it's there, though: look at the .pyc (or .pyo if you have the optimizer turned on) files that are generated for modules that you import.
Also, it does not compile to the native machine's code. Instead, it compiles to a byte code that is used by a virtual machine. The virtual machine is itself a compiled program. This is very similar to how Java works; so similar, in fact, that there is a Python variant (Jython) that compiles to the Java Virtual Machine's byte code instead! There's also IronPython, which compiles to Microsoft's CLR (used by .NET). (The normal Python byte code compiler is sometimes called CPython to disambiguate it from these alternatives.)
You have two ways to test it out:
type python -i address.py in the terminal. This will run the script and enter the python shell.
You enter the python shell and then type from address.py import AddressBook.
On both ways, you can
play around with your code.
I'm looking to write a Lua script and have it also execute something from Python source code as well, as if it went like so:
#!/bin/lua
-- begin lua part
print "Hello"
-- begin python part
Somehow_Executes_Python {
print "Hello" #In python, of course
}
-- End Script
Getting the idea?
I'm not sure if it's even possible, but if I can somehow implement foreign source code in controlled blocks, that would be great. I've seen other things about calling them from a different file/ link/ source, but I'm looking to have it work directly from inside of the lua source code, not from a different file entirely.
The simplest approach would be something along these lines:
#!/usr/bin/env lua
local python = function(code)
local file = assert(io.popen('python', 'w'))
file:write(code)
file:close()
end
-- begin lua part
print "Hello from Lua"
--begin python part
python [=[
print "Hello from Python"
]=]
-- End Script
Line-by-line explanation (without code highlighting, it seems that it is broken for Lua on the SO):
#!/usr/bin/env lua
-- The above is a more sure-fire way to run Lua on linux from a shebang
-- This function runs python code as follows
local python = function(code)
-- It opens a write pipe to the python executable
local file = assert(io.popen('python', 'w'))
-- pipes the code there
file:write(code)
-- and closes the file
file:close()
-- This is an equivalent of running
-- $ python <code.py
-- in the shell.
end
-- Begin Lua part
-- I added "from Lua" to better see in the output what works or not.
print "Hello from Lua"
-- Begin Python part
-- We're calling our python code running function,
-- passing Lua long string to it. This is equivalent of
-- python('print "Hello from Python"')
python [=[
print "Hello from Python"
]=]
-- End Script
I imagine you would like to have at least some interoperability between Lua and Python code. It is a bit more difficult to implement and the way you should do it highly depends on the details of the problem you're actually solving.
The cleanest way would probably to create a socket pair of one kind or another and to make Lua and Python code to talk over it.
Solutions where you may read a variable or call a function from one VM (say Lua) in another (say Python) and vice-versa usually lead to a mess for a multitude of reasons (I tried a lot of them and implemented several myself).
There is a python-lua package called Lupa. Here's the documentation. See if that helps.
I am trying to make some of my code Python 2 and 3 compatible.
At the moment I am struggling with functions like range/xrange and methods like dict.items/dict.iteritems. Ideally I would like my code to be able to use the former in Python 3.x and the latter in Python 2.x.
Using if/else seems to me to be the easiest way to implement this:
if py >= 3:
for item in array.items()
...
else:
for item in array.iteritems()
However, doing like that results in lots of repeated and ugly code. Is there a better way to do that using only the standard library? Can I just state somewhere at the beginning of the code to always use range/dict.items if py >= 3 and xrange/dict.iteritems if not?
Is it possible to do something like this?
if py < 3:
use xrange as range
I have looked around and I know that several libraries, like six o futurize) are used to solve this issue. However I am working on a server that run only python 2.7 and I am not allowed to install any extra libraries on it. I have some python3 code I would like to use but I also want to maintain only one version of the code.
The simple, "Don't Make Me Think!" solution I use is to start simple scripts with:
#!/usr/bin/env python
# just make sure that Python 3 code runs fine with 2.7+ too ~98% of the time :)
from __future__ import (division, print_function, absolute_import,
unicode_literals)
from builtins import int
try:
from future_builtins import ascii, filter, hex, map, oct, zip
except:
pass
import sys
if sys.version_info.major > 2:
xrange = range
(Extra tip to stop most pep8 linters for unnecessarily yelling at you for this: move last 3 lines inside and at the top of the try block above)
But the only case I use this is basically "shell scripts that were too large and hairy so I quickly rewrote them to Python and I just want them to run under both Python 2 and 3 with 0 dependencies". Please do NOT use this in real application/library code until you know exactly what are the consequences of all the lines above, and if they are enough for your use case.
Also, the "solution" in this case for .iteritems is "just don't use it", ignore memory use optimizations and just always use .items instead - if this matters, it means you're not writing a "0 dependencies simple script" anymore, so just pick Python 3 and code for it (or Python 2 if you need to pretend we're in 2008).
Also, check these resources to get a proper understanding:
http://python-future.org/compatible_idioms.html
http://lucumr.pocoo.org/2011/1/22/forwards-compatible-python/
https://wiki.python.org/moin/PortingToPy3k/BilingualQuickRef
(NOTE: I'm answering this already answered question mainly because the accepted answers roughly translates to "you are stupid and this is dumb" and I find this very rude for an SO answer: no matter how dumb the question, and how "wrong" to actually answer it, a question deserves a real answer._
import sys
if sys.version_info.major > 2:
xrange = range
But as Wim implies, this is basically rewriting six yourself.
And as you can see, six does a lot more that handling range. Just e.g. look at the _moved_attributes list in the six source code.
And while Python comes with "batteries included", its standard library is not and cannot be all-encompassing. Nor is it devoid of flaws.
Sometimes there are better batteries out there, and it would be a waste not to use them. Just compare urllib2 with requests. The latter is much nicer to work with.
I would recommend writing for py2 or py3 in your projects's modules, but not mix them together and not include any sort of 2/3 checks at all. Your program's logic shouldn't have to care about its version of python, except maybe for avoiding functions on builtin objects that conflict.
Instead, import * from your own compatiblity layer that fixes the differences between your framework and use shadowing to make it transparent to your actual project's module.
For instance, in the compatibility module, you can write Roland Smith's substition for range/xrange, and in your other modules you add "from compatibility import *". Doing this, every module can use "xrange" and the compatibility layer will manage the 2/3 differences.
Unfortunately it won't solve existing objects functions such as dict.iteritems; typically you would monkey-patch the dict methods, but it is not possible on builtin types (see https://stackoverflow.com/a/192857/1741414). I can imagine some workarounds:
Function wrappers (essentially sobolevn's answer)
Don't use .items() functions at all; use simple loops on keys and then access the dictionary with those keys:
for key in my_dict:
value = my_dict[key]
# rest of code goes here
I guess you are mixing up array and dict in this case.
If you are restricted in using 3-d party libraries for any reason, so why not like this:
def iterate_items(to_iterate):
if py >= 3:
return to_iterate.items()
else:
return to_iterate.iteritems()
And then use it:
for item in iterate_items(your_dict):
...
import sys
VERSION = float("{}.{}".format(sys.version_info.major, sys.version_info.minor))
And by using this we can write conditional code for desired versions.
if VERSION >= 3.5:
from subprocess import run as _run
else:
from subprocess import call as _run
Does a easy to use Ruby to Python bridge exist? Or am I better off using system()?
You could try Masaki Fukushima's library for embedding python in ruby, although it doesn't appear to be maintained. YMMV
With this library, Ruby scripts can directly call arbitrary Python modules. Both extension modules and modules written in Python can be used.
The amusingly named Unholy from the ingenious Why the Lucky Stiff might also be of use:
Compile Ruby to Python bytecode.
And, in addition, translate that
bytecode back to Python source code
using Decompyle (included.)
Requires Ruby 1.9 and Python 2.5.
gem install rubypython
rubypython home page
I don't think there's any way to invoke Python from Ruby without forking a process, via system() or something. The language run times are utterly diferent, they'd need to be in separate processes anyway.
If you want to use Python code like your Python script is a function, try IO.popen .
If you wanted to reverse each string in an array using the python script "reverse.py", your ruby code would be as follows.
strings = ["hello", "my", "name", "is", "jimmy"]
#IO.popen: 1st arg is exactly what you would type into the command line to execute your python script.
#(You can do this for non-python scripts as well.)
pythonPortal = IO.popen("python reverse.py", "w+")
pythonPortal.puts strings #anything you puts will be available to your python script from stdin
pythonPortal.close_write
reversed = []
temp = pythonPortal.gets #everything your python script writes to stdout (usually using 'print') will be available using gets
while temp!= nil
reversed<<temp
temp = pythonPortal.gets
end
puts reversed
Then your python script would look something like this
import sys
def reverse(str):
return str[::-1]
temp = sys.stdin.readlines() #Everything your ruby programs "puts" is available to python through stdin
for item in temp:
print reverse(item[:-1]) #Everything your python script "prints" to stdout is available to the ruby script through .gets
#[:-1] to not include the newline at the end, puts "hello" passes "hello\n" to the python script
Output:
olleh
ym
eman
si
ymmij
For python code to run the interpreter needs to be launched as a process. So system() is your best option.
For calling the python code you could use RPC or network sockets, got for the simplest thing which could possibly work.