python experiment

Headers, Bindings, Libraries for use with FreeBASIC, Please include example of use to help ensure they are tested and usable.
srvaldez
Posts: 3379
Joined: Sep 25, 2005 21:54

Re: python experiment

Post by srvaldez »

It might have something to do with setting the __name__ variable for the python script.
@caseih, that makes sense
jj2007
Posts: 2326
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: python experiment

Post by jj2007 »

srvaldez wrote:the one hairy detail is: how to exchange data between the python script and FB, sure you could write it to a file and then read it, but that's not very efficient.
Maybe use a pipe?
dodicat
Posts: 7983
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: python experiment

Post by dodicat »

Srvaldez.
Test 64 bits.
When I use
#Define PyRun_AnyFile(fp, name_) PyRun_AnyFileExFlags(fp, name_, 0, NULL)
i.e.
dim as file ptr fp=fopen("time.py","rb")
PyRun_AnyFile(fp,"time.py")

I get the interpreter command line >>>
srvaldez
Posts: 3379
Joined: Sep 25, 2005 21:54

Re: python experiment

Post by srvaldez »

@dodicat
the example I posted is flawed, it does not check whether fp contains a valid pointer, I suspect that in your test fopen("time.py","rb") failed to open the file, perhaps if you use the full path it will work.
srvaldez
Posts: 3379
Joined: Sep 25, 2005 21:54

Re: python experiment

Post by srvaldez »

@jj2007
I did a fair amount of web searching and pipes were among the hits, it's a pity that there's no simple and efficient way to exchange data.
srvaldez
Posts: 3379
Joined: Sep 25, 2005 21:54

Re: python experiment

Post by srvaldez »

@dodicat
PyRun_AnyFile will also accept stdin as a valid file, my guess is that if fp=0 then the default is stdin and therefore you are greeted with the python prompt.
jj2007
Posts: 2326
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: python experiment

Post by jj2007 »

srvaldez wrote:I did a fair amount of web searching and pipes were among the hits, it's a pity that there's no simple and efficient way to exchange data.
I'm no Python expert, so it would cost me a steep learning curve, but memory-mapped files are also an option. Under Windows, you can also share data via a DLL.
srvaldez
Posts: 3379
Joined: Sep 25, 2005 21:54

Re: python experiment

Post by srvaldez »

thanks for the suggestion, but this is more than I am willing to invest, after all, it's just a cursory look at embedding python in FB.
caseih
Posts: 2157
Joined: Feb 26, 2007 5:32

Re: python experiment

Post by caseih »

srvaldez wrote:@jj2007
I did a fair amount of web searching and pipes were among the hits, it's a pity that there's no simple and efficient way to exchange data.
There are several methods. You can create a Python object from FB, such as a Python list, and then insert data into that list. You could also cast your FB data structure as a zstring ptr and then pass to a Python function as a "bytes" object, and then in Python use the ctypes or struct module to access the data out of this byte array. The final alternative is to create a Python function using the C API and have that function pass data between FB and Python. See https://stackoverflow.com/questions/139 ... hon-script. Not exactly super easy, but not that hard either. Lua is probably easier.
srvaldez
Posts: 3379
Joined: Sep 25, 2005 21:54

Re: python experiment

Post by srvaldez »

@caseih
perhaps another time, somehow I lack the motivation, speaking of Lua, I came across Lunatic Python
dodicat
Posts: 7983
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: python experiment

Post by dodicat »

Trivial with files, not much success yet with pipes or other methods suggested by caseih.
There's always tomorrow.

Code: Select all

 
#inclib "python37"
#include "file.bi"
'=====================================
Declare Sub  Pyinit Cdecl  Alias "Py_Initialize"()
Declare Function runstring Cdecl Alias "PyRun_SimpleString"(Byval s As zstring Ptr) As Integer
Declare Sub setname Cdecl Alias "Py_SetProgramName"(As String)
Declare Function PyMain Cdecl Alias "Py_Main"(As Long=0,Byref As zstring Ptr =0) As Long
Declare Sub Pyfinish Cdecl Alias "Py_Finalize"()

Sub runfile(filename As String)
    runstring("exec(open('"+filename+"').read())") 
End Sub

Function loadfile(file As String) As String
    If Fileexists(file)=0 Then Print file;" not found":Sleep:End
    Var  f=Freefile
    Open file For Binary Access Read As #f
    Dim As String text
    If Lof(f) > 0 Then
        text = String(Lof(f), 0)
        Get #f, , text
    End If
    Close #f
    Return text
End Function


Function max(a() As Double) As Double
    Dim As String s="L=["
    For n As Long=Lbound(a) To Ubound(a)
        s+=Str(a(n))+","
    Next
    s=Rtrim(s,",")
    s+="]"
    runstring s
    runstring "print('data = ',L)"
    runstring "x=max(L)"
    runstring "fp=open('out.txt','w')"
    runstring "fp.write(str(x))"
    runstring "fp.close()"
    max=Val(loadfile("out.txt"))
    Kill "out.txt"
    if fileexists("out.txt") then print "deletion failed"
End Function

Dim As Double z(1 To ...)={4.8,-6.9,3.2,56,-8,34.7,56.1,0,-67,72.6,78.0003,34.3,-9}

pyinit
Print max(z());"  is the maximum"
pyfinish
Sleep 
jj2007
Posts: 2326
Joined: Oct 23, 2016 15:28
Location: Roma, Italia
Contact:

Re: python experiment

Post by jj2007 »

caseih wrote:The final alternative is to create a Python function using the C API and have that function pass data between FB and Python. See https://stackoverflow.com/questions/139 ... hon-script.
The SOF article speaks only about passing data to Python. You might look at Sending WM_COPYDATA in Python with ctypes. Instead of using FindWindow, pass the FB window handle to Python.
caseih
Posts: 2157
Joined: Feb 26, 2007 5:32

Re: python experiment

Post by caseih »

jj2007 wrote:
caseih wrote:The final alternative is to create a Python function using the C API and have that function pass data between FB and Python. See https://stackoverflow.com/questions/139 ... hon-script.
The SOF article speaks only about passing data to Python. You might look at Sending WM_COPYDATA in Python with ctypes. Instead of using FindWindow, pass the FB window handle to Python.
The same mechanisms transfer data two ways. Once the list object is created in FB, the Python code can add objects to it, and back in FB you can grab them out of the list and unpack their data.

Also you can call Python functions from the API, and unpack the result from the resulting PyObject. Also you can create a wrapper that python can use to call your FB functions. Really it's all there in the API. Been years since I last did it, but I have done it before in C. There are some tutorials (written in C of course) for using the Python C API on the main web site.
TJF
Posts: 3809
Joined: Dec 06, 2009 22:27
Location: N47°, E15°
Contact:

Re: python experiment

Post by TJF »

caseih wrote:Also you can create a wrapper that python can use to call your FB functions. Really it's all there in the API. Been years since I last did it, but I have done it before in C. There are some tutorials (written in C of course) for using the Python C API on the main web site.
In my libpruio project I auto-create a Python ctypes wrapper from fb source code by fbdoc and the py_ctypes plugin. See file src/python/CMakeLists.txt for details.

Regards
dodicat
Posts: 7983
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: python experiment

Post by dodicat »

ctypes looks like a system install, I can find no simple download to add to the working folder.

Python is very slow compared to fb .
I expected this of course due to python's integer data type.
64 bit python nevertheless seems much faster than 32 bit python for this example:
A nice touch is that you can optimise -gen gcc to -O(infinity) and it won't make a hoot of a difference.

Code: Select all

#inclib "python37"

'=====================================
Declare Sub  Pyinit Cdecl  Alias "Py_Initialize"()
Declare Function runstring Cdecl Alias "PyRun_SimpleString"(Byval s As zstring Ptr) As Integer
Declare Sub setname Cdecl Alias "Py_SetProgramName"(As String)
Declare Function PyMain Cdecl Alias "Py_Main"(As Long=0,Byref As zstring Ptr =0) As Long
Declare Sub Pyfinish Cdecl Alias "Py_Finalize"()

Sub runfile(filename As String)
    runstring("exec(open('"+filename+"').read())") 
End Sub

Sub runfileex(filename As String,flag As boolean=true)
    runstring( "fp=open('"+filename+"','r')")
    runstring("codestring=fp.read()")
    If flag Then runstring("print(codestring)")
    runstring("exec(codestring)")
End Sub

Sub savefile(filename As String,file_content As String)
    Dim As Integer n
    n=Freefile
    If Open (filename For Binary Access Write As #n)=0 Then
        Put #n,,file_content
        Close
    Else
        Print "Unable to save " + filename
    End If
End Sub
'==========================================

Function isprime(n As Ulongint) As long
    If (n=2) Or (n=3) Then Return -1
    If n Mod 2 = 0 Then Return 0
    If n Mod 3 = 0 Then Return 0
    Dim As Ulongint limit=Sqr(N)+1
    For I As Ulongint = 6 To limit Step 6
        If n Mod (i-1) = 0 Then Return 0
        If n Mod (i+1) = 0 Then Return 0
    Next I
    Return -1
End Function

Sub CreatePyIsprime
    Dim As String s
    s="import math"+Chr(10)
    s+="def isprime(n):"+Chr(10)
    s+=" if ((n==2) or (n==3)):"+Chr(10)
    s+="  return -1"+Chr(10)
    s+=" if (n % 2 == 0):"+Chr(10)
    s+="  return 0"+Chr(10)
    s+=" if ((n % 3) == 0) :"+Chr(10)
    s+="  return 0"+Chr(10)
    s+=" limit=math.sqrt(n)+1"+Chr(10)
    s+=" for i in range(6,int(limit),6):"+Chr(10)
    s+="  if (n % (i-1) == 0):"+Chr(10)
    s+="   return 0"+Chr(10)
    s+="  if (n % (i+1) == 0):"+Chr(10)
    s+="   return 0"+Chr(10)
    s+=" return -1"+Chr(10)
    savefile("Pyisprime.py",s)
End Sub


function test as long
  CreatePyIsPrime  
Print "Primes in range 100000000000000 to  100000000000300"
Print "Python"
Dim As String script

script ="import Pyisprime"+Chr(10)
script+="for n in range(100000000000000,100000000000300):"+Chr(10)
script+=" if(Pyisprime.isprime(n)==-1):"+Chr(10)
script+="  print(n)"

Dim As Double t=Timer
setname "Compare speeds"
Pyinit
runstring(script)
Pyfinish
Print "time ";int((Timer-t)*1000);" milliseconds"
Print

Print "FB"
t=Timer
For n As Longint=100000000000000 To 100000000000300
    If isprime(n) Then Print str(n)
Next
Print "time ";int((Timer-t)*1000);;" milliseconds"
print
print "Press a key to end . . ."
sleep
return 0
end function


end test


  
Post Reply