python experiment

External libraries (GTK, GSL, SDL, Allegro, OpenGL, etc) questions.
dodicat
Posts: 5913
Joined: Jan 10, 2006 20:30
Location: Scotland

python experiment

Postby dodicat » Jul 03, 2019 0:44

fb 64 bit windows.
Run a simple python script (string) from within a folder

https://www.mediafire.com/file/c6sdiqvnyvf62s7/pythonrun.zip/file
Here is the python help file.

http://www.mediafire.com/file/n8h2x0r2s ... a.zip/file

No need to expand it, just put it in the pythonrun folder (from the previous link)

Here is an updated test file

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 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
'=====================================

Dim As String f
f= "def fib(n):"+Chr(10)
f+="    v1, v2, v3 = 1, 1, 0"+Chr(10)
f+="    for rec in bin(n)[3:]:" +Chr(10)
f+="        calc = v2*v2" + Chr(10)
f+="        v1, v2, v3 = v1*v1+calc, (v1+v3)*v2, calc+v3*v3"+Chr(10)
f+="        if rec=='1':    v1, v2, v3 = v1+v2, v1, v2"+Chr(10)
f+="    return v2"+Chr(10)

f+="for i in range(0,200):" +Chr(10)
f+=" print('fibonacci',i,'=',fib(i))"


setname "first" 'advised to set a program name
pyinit()        'start python (must do)
runstring (f)

Print

'string script by srvaldez
f="class Expr:"+Chr(10)
f+="  def __add__(self, other):"+Chr(10)
f+="    return Plus(self, other)"+Chr(10)
f+="  def __mul__(self, other):"+Chr(10)
f+="    return Times(self, other)"+Chr(10)

f+="class Int(Expr):"+Chr(10)
f+="  def __init__(self, n):"+Chr(10)
f+="    self.n = n"+Chr(10)
f+="  def d(self, v):"+Chr(10)
f+="    return Int(0)"+Chr(10)
f+="  def __str__(self):"+Chr(10)
f+="    return str(self.n)"+Chr(10)

f+="class Var(Expr):"+Chr(10)
f+="  def __init__(self, var):"+Chr(10)
f+="    self.var = var"+Chr(10)
f+="  def d(self, v):"+Chr(10)
f+="    return Int(self.var == v and 1 or 0)"+Chr(10)
f+="  def __str__(self):"+Chr(10)
f+="    return self.var"+Chr(10)

f+="class Plus(Expr):"+Chr(10)
f+="  def __init__(self, a, b):"+Chr(10)
f+="    self.e1 = a"+Chr(10)
f+="    self.e2 = b"+Chr(10)
f+="  def d(self, v):"+Chr(10)
f+="    return Plus(self.e1.d(v), self.e2.d(v))"+Chr(10)
f+="  def __str__(self):"+Chr(10)
f+="    return ""(%s +%s)""% (self.e1, self.e2)"+Chr(10)

f+="class Times(Expr):"+Chr(10)
f+="  def __init__(self, a, b):"+Chr(10)
f+="    self.e1 = a"+Chr(10)
f+="    self.e2 = b"+Chr(10)
f+="  def d(self, v):"+Chr(10)
f+="    return Plus(Times(self.e1, self.e2.d(v)), Times(self.e1.d(v), self.e2))"+Chr(10)
f+="  def __str__(self):"+Chr(10)
f+="    return ""(%s *%s)""% (self.e1, self.e2)"+Chr(10)

f+="if __name__ == ""__main__"":"+Chr(10)
f+="  x = Var(""x"")"+Chr(10)
f+="  a = Var(""a"")"+Chr(10)
f+="  b = Var(""b"")"+Chr(10)
f+="  c = Var(""c"")"+Chr(10)
f+="  e = a * x * x + b * x + c"+Chr(10)
f+="  print (""d(%s, x) =%s""% (e, e.d(""x"")))"+Chr(10)
Print
Print "result from srvaldez's script:"
runstring f
Print
Print "result from running a file from disk:"

'save time.py to disk
savefile("time.py","import time"+Chr(10)+"print('Today is', time.ctime())")
'run a .py file from disk
runfile("time.py")
Print

Print "factorial of 1000 = "
Dim As Double t=Timer
runstring("import math"+Chr(10)+"x=1000"+Chr(10)+"print(math.factorial(x))")
Print "time taken ";Timer-t
Print
Kill "time.py"  'optional
Pyfinish        '(should do)

Print "Now run the interpreter ..  exit() to finish  "
Print PyMain()


Sleep
 


For a simple python set up, basically the files are
pythonXX.dll
pythonXX.zip - keep zipped
vcruntime140.dll
And for the help file pydoc_data.zip from above.(optional)
And the code above to call some basic functions.
Last edited by dodicat on Jul 04, 2019 11:07, edited 1 time in total.
srvaldez
Posts: 2063
Joined: Sep 25, 2005 21:54

Re: python experiment

Postby srvaldez » Jul 03, 2019 12:15

thanks dodicat
tested ok also on macOS using either python 2.7 or 3.7
here's a script from http://www.codecodex.com/wiki/Calculate ... ive#Python

Code: Select all

f="class Expr:"+Chr(10)
f+="  def __add__(self, other):"+Chr(10)
f+="    return Plus(self, other)"+Chr(10)
f+="  def __mul__(self, other):"+Chr(10)
f+="    return Times(self, other)"+Chr(10)

f+="class Int(Expr):"+Chr(10)
f+="  def __init__(self, n):"+Chr(10)
f+="    self.n = n"+Chr(10)
f+="  def d(self, v):"+Chr(10)
f+="    return Int(0)"+Chr(10)
f+="  def __str__(self):"+Chr(10)
f+="    return str(self.n)"+Chr(10)

f+="class Var(Expr):"+Chr(10)
f+="  def __init__(self, var):"+Chr(10)
f+="    self.var = var"+Chr(10)
f+="  def d(self, v):"+Chr(10)
f+="    return Int(self.var == v and 1 or 0)"+Chr(10)
f+="  def __str__(self):"+Chr(10)
f+="    return self.var"+Chr(10)

f+="class Plus(Expr):"+Chr(10)
f+="  def __init__(self, a, b):"+Chr(10)
f+="    self.e1 = a"+Chr(10)
f+="    self.e2 = b"+Chr(10)
f+="  def d(self, v):"+Chr(10)
f+="    return Plus(self.e1.d(v), self.e2.d(v))"+Chr(10)
f+="  def __str__(self):"+Chr(10)
f+="    return ""(%s +%s)""% (self.e1, self.e2)"+Chr(10)

f+="class Times(Expr):"+Chr(10)
f+="  def __init__(self, a, b):"+Chr(10)
f+="    self.e1 = a"+Chr(10)
f+="    self.e2 = b"+Chr(10)
f+="  def d(self, v):"+Chr(10)
f+="    return Plus(Times(self.e1, self.e2.d(v)), Times(self.e1.d(v), self.e2))"+Chr(10)
f+="  def __str__(self):"+Chr(10)
f+="    return ""(%s *%s)""% (self.e1, self.e2)"+Chr(10)

f+="if __name__ == ""__main__"":"+Chr(10)
f+="  x = Var(""x"")"+Chr(10)
f+="  a = Var(""a"")"+Chr(10)
f+="  b = Var(""b"")"+Chr(10)
f+="  c = Var(""c"")"+Chr(10)
f+="  e = a * x * x + b * x + c"+Chr(10)
f+="  print (""d(%s, x) =%s""% (e, e.d(""x"")))"+Chr(10)


if you have numpy, scipy and mathplotlib installed, you can run the following script https://www.scipy.org/getting-started.html

Code: Select all

f="import argparse"+Chr(10)

f+="import numpy as np"+Chr(10)
f+="from scipy import special, optimize"+Chr(10)
f+="import matplotlib.pyplot as plt"+Chr(10)

f+="def main():"+Chr(10)
f+="    # Parse command-line arguments"+Chr(10)
f+="    parser = argparse.ArgumentParser(usage=__doc__)"+Chr(10)
f+="    parser.add_argument(""--order"", type=int, default=3, help=""order of Bessel function"")"+Chr(10)
f+="    parser.add_argument(""--output"", default=""plot.png"", help=""output image file"")"+Chr(10)
f+="    args = parser.parse_args()"+Chr(10)

f+="    # Compute maximum"+Chr(10)
f+="    f = lambda x: -special.jv(args.order, x)"+Chr(10)
f+="    sol = optimize.minimize(f, 1.0)"+Chr(10)

f+="    # Plot"+Chr(10)
f+="    x = np.linspace(0, 10, 5000)"+Chr(10)
f+="    plt.plot(x, special.jv(args.order, x), '-', sol.x, -sol.fun, 'o')"+Chr(10)

f+="    # Produce output"+Chr(10)
f+="    plt.savefig(args.output, dpi=96)"+Chr(10)

f+="if __name__ == ""__main__"":"+Chr(10)
f+="    main()"+Chr(10)
dodicat
Posts: 5913
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: python experiment

Postby dodicat » Jul 03, 2019 13:10

Thanks srvaldez.
Here is an improved (slightly) test.
Should finish the tasks and have the interpreter prompt at the end.
I had to download pydoc_data/topics.py into the folder to get the help working.

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 integer=0,as zstring ptr=0) as integer
Declare Sub Pyfinish cdecl Alias "Py_Finalize"()

Sub savefile(filename As String,p As String)
    Dim As Integer n
    n=Freefile
    If Open (filename For Binary Access Write As #n)=0 Then
        Put #n,,p
        Close
    Else
        Print "Unable to save " + filename
    End If
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


Dim As String f
f= "def fib(n):"+Chr(10)
f+="    v1, v2, v3 = 1, 1, 0"+Chr(10)
f+="    for rec in bin(n)[3:]:" +Chr(10)
f+="        calc = v2*v2" + Chr(10)
f+="        v1, v2, v3 = v1*v1+calc, (v1+v3)*v2, calc+v3*v3"+Chr(10)
f+="        if rec=='1':    v1, v2, v3 = v1+v2, v1, v2"+Chr(10)
f+="    return v2"+Chr(10)

f+="for i in range(0,400):" +Chr(10)
f+=" print('fibonacci',i,'=',fib(i))"


 setname "first" 'advised to set a program name
 pyinit()        'start python (must do)
 runstring (f)

 Print

'save time.py to disk
 savefile("time.py","import time"+Chr(10)+"print('Today is', time.ctime())")
 
 
 runstring(loadfile("time.py"))
 print "factorial of 1000 = "
 dim as double t=timer
 runstring("import math"+chr(10)+"x=1000"+chr(10)+"print(math.factorial(x))")
 
 print "time taken ";timer-t
 print
 kill "time.py"  'optional
 Pyfinish '(should do)
 
 PyMain() '' call interpreter command line
 

 Sleep
 

Tried on 32 bit python36 also, everything OK except calling the command line at the end.
srvaldez
Posts: 2063
Joined: Sep 25, 2005 21:54

Re: python experiment

Postby srvaldez » Jul 03, 2019 13:55

dodicat
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.
caseih
Posts: 1369
Joined: Feb 26, 2007 5:32

Re: python experiment

Postby caseih » Jul 03, 2019 14:03

[quote="dodicat"]

Code: Select all

PyMain cdecl alias "Py_Main"(as integer=0,as zstring ptr=0) as integer

I can't speak to Win32, but I'm pretty sure on Linux and Mac, that a C int is always 32-bit, even on 64-bit systems. So this declaration should probably be Long instead of Integer. I think this is one of the few type incompatibilities between C and FB. At least that's what I remember that a C int is equivalent to a FB Long.
caseih
Posts: 1369
Joined: Feb 26, 2007 5:32

Re: python experiment

Postby caseih » Jul 03, 2019 14:06

srvaldez wrote:dodicat
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.
If we had the complete Python API declared for FB then you would just create a Python object around your FB data and you'd have a two-way bridge. The full Python API is not that complicated, but there are a ton of header files that work together to make it up. Maybe enough of the API and UDTs can be declared as needed: https://docs.python.org/3/extending/extending.html
MrSwiss
Posts: 3220
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: python experiment

Postby MrSwiss » Jul 03, 2019 15:12

caseih wrote: At least that's what I remember that a C int is equivalent to a FB Long.
It's documented in FB-Manual, too ... see: Comparison of C/C++ and FreeBASIC
oyster
Posts: 183
Joined: Oct 11, 2005 10:46

Re: python experiment

Postby oyster » Jul 03, 2019 15:40

a related question, is there an easy way to write multilines string in fb?

the


f="sth"
f+="STH"

is waste of kbd
dodicat
Posts: 5913
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: python experiment

Postby dodicat » Jul 03, 2019 16:01

srvaldez wrote:dodicat
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.

at the moment I am testing simple .py files (from rosetta code e.t.c.)
runstring("exec(open('time.py').read())")
runstring(loadfile("time.py"))
Both these work.
I cannot get PyRun_AnyFile to work, but I am not alone according to google.
oyster, you could do

Code: Select all


dim as string s=!"abc\n"+_
                !"def\n"+_
                 "zzz"
                print s
                sleep

I have tried using longs in 32 bit fbc, but I still cannot access the python command line interpreter with "Py_Main"
OK in 64 bits.
MrSwiss
Posts: 3220
Joined: Jun 02, 2013 9:27
Location: Switzerland

Re: python experiment

Postby MrSwiss » Jul 03, 2019 16:27

dodicat wrote:I have tried using longs in 32 bit fbc, but I still cannot access the python command line interpreter with "Py_Main"
In this case, the C data type is probably long (C's long), which comes close to 'integer',
but especially on WIN, isn't 100% compatible ...
see: Comparison of integer data types: FreeBASIC vs. C/C++ (using GCC)

@oyster, you question is IMO "off topic", because a string is technically a UDT
and therefore, not really a base-data-type (missing relationship).
caseih
Posts: 1369
Joined: Feb 26, 2007 5:32

Re: python experiment

Postby caseih » Jul 03, 2019 16:40

I'm pretty sure the API uses C int regardless of 32 or 64-bit host. Py_Main is designed to be passed the same data structures that a C main program is passed, which is int and a t_wchar **. On Linux everything is UTF-8, so t_wchar is the equivalent of char. So the declaration is probably more along the lines of:

Code: Select all

declare function Py_Main cdecl alias "Py_Main" ( as long=0, as zstring ptr ptr = 0)


Although in Windows I think it would be WSTRING PTR PTR.

Although that doesn't explain why Py_Main doesn't work at all.
srvaldez
Posts: 2063
Joined: Sep 25, 2005 21:54

Re: python experiment

Postby srvaldez » Jul 03, 2019 19:42

dodicat wrote:I cannot get PyRun_AnyFile to work, but I am not alone according to google.

from the documentation
int PyRun_SimpleFileExFlags(FILE *fp, const char *filename, int closeit, PyCompilerFlags *flags)
Similar to PyRun_SimpleStringFlags(), but the Python source code is read from fp instead of an in-memory string. filename should be the name of the file, it is decoded from the filesystem encoding (sys.getfilesystemencoding()). If closeit is true, the file is closed before PyRun_SimpleFileExFlags returns.

Note On Windows, fp should be opened as binary mode (e.g. fopen(filename, "rb"). Otherwise, Python may not handle script file with LF line ending correctly.

try this

Code: Select all

#Inclib "python3.7"

#Include "crt/stdio.bi"

Declare Sub  Pyinit  Alias "Py_Initialize"()
Declare Sub Pyfinish Alias "Py_Finalize"()
Declare Function PyRun_InteractiveOneFlags Alias "PyRun_InteractiveOneFlags" (Byval fp As FILE Ptr, Byval filename As Const Zstring Ptr, Byval flags As Integer /'PyCompilerFlags ptr'/) As Long
Declare Function PyRun_AnyFileExFlags Alias "PyRun_AnyFileExFlags" (Byval fp As FILE Ptr, Byval filename As Const Zstring Ptr, Byval closeit As Long, Byval flags As Integer /'PyCompilerFlags ptr'/) As Long

#Define NULL 0
#Define PyRun_AnyFile(fp, name_) PyRun_AnyFileExFlags(fp, name_, 0, NULL)

Dim As FILE Ptr fp= fopen("example.py", "rb")
pyinit()
PyRun_AnyFile(fp, "example.py")
Pyfinish
Print
Sleep

I really don't understand why PyRun_AnyFileExFlags(fp, name_, 0, NULL) needs a filename when it already has a file pointer
dodicat
Posts: 5913
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: python experiment

Postby dodicat » Jul 03, 2019 19:51

Thanks srvaldez, I'll try later.
I made a little sub to run a script file.

Code: Select all

sub runfile(filename as string)
   runstring("exec(open('"+filename+"').read())")
end sub
 

These functions like "PyRun_AnyFileExFlags" have to go through the motions of opening and running anyway I guess.
caseih
Posts: 1369
Joined: Feb 26, 2007 5:32

Re: python experiment

Postby caseih » Jul 04, 2019 4:53

srvaldez wrote:I really don't understand why PyRun_AnyFileExFlags(fp, name_, 0, NULL) needs a filename when it already has a file pointer
It might have something to do with setting the __name__ variable for the python script.
dodicat
Posts: 5913
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: python experiment

Postby dodicat » Jul 04, 2019 7:26

To get PyMain in 32 bits (to get the interpreter command line)

Code: Select all

 declare function PyMain cdecl alias "Py_Main"(as long=0,byref as zstring ptr =0) as long


Python 3.6.0 (v3.6.0:41df79263a11, Dec 23 2016, 07:18:10) [MSC v.1900 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>>

Return to “Libraries”

Who is online

Users browsing this forum: No registered users and 3 guests