Back to coding...

ilan

Expert
Licensed User
Longtime User
After a short break, I’m back to coding.
I’ve been playing around with PyBridge, and I have to say, this might be the most impressive library Erel has created in years. I already finished my B4J server using a great Python library I downloaded, and everything works beautifully.

Now I’m working on the B4X clients, and I’ll upload them to the store soon. The huge advantage here is how easily we can use external Python libraries. I even configured the server to use the
latest Python framework instead of the minimal version bundled with B4J, and it runs perfectly.

B4X:
Dim opt As PyOptions = Py.CreateOptions("C:\Users\ilan1\AppData\Local\Programs\Python\Python314\python.exe")

This is a game changer. We can build so many powerful things while still staying in our familiar environment.


THANK YOU @Erel 🙏 🙏 🙏 🙏
 

hatzisn

Expert
Licensed User
Longtime User
I have tried it too. It is incredible. And the fact that it is implementable in B4J it is a plus^2. The only caveat is if the python code has long processing time you cannot implement it easily in a WebApp because the calls are sequential. Although I cannot understand why is this happening... Since it is communication with open ports why don't we run more instances of the bridge in the Java part (or one instance with multiple open ports in different threads) and the Python part will just communicate in different ports with the Java side bridge as different instances (I am not familiar with threads in the Python side). It is just a Try-Except block to select the appropriate port in python side or am I thinking it is easy because I have not checked the implementation?
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
I agree that PyBridge is a great library and open many options that were previously difficult to achieve.

@hatzisn the solution for such cases is usually to implement it with async methods that do not block the python process. PyBridge support such methods with Py.RunCodeAwait and Wrapper.RunAwait.
 

ilan

Expert
Licensed User
Longtime User
@hatzisn the solution for such cases is usually to implement it with async methods that do not block the python process. PyBridge support such methods with Py.RunCodeAwait and Wrapper.RunAwait.
i did it like this:

B4X:
Wait For (pyw.Fetch) Complete (Result As PyWrapper)

and also added at the end of the function:

B4X:
StopMessageLoop

after its done i call again:

B4X:
StartMessageLoop

the important thing is NOT TO RUN A ASYNC METHOD INSIDE THE HANDLER!!

i tried running 50 calls to the server at the same time and all went through and all responded back.

B4X:
for /l %i in (1,1,50) do curl "http://localhost/ai/apitest1?text=בערב קיץ חמים ישב דניאל על ספסל העץ שבקצה החצר והרוח נשאה ריח של יסמין והירח עלה לאט מעל הגגות"

if there is a better solution, could you please upload a simple version how to make async calls to PyBridge?
 

Magma

Expert
Licensed User
Longtime User
i did it like this:

B4X:
Wait For (pyw.Fetch) Complete (Result As PyWrapper)

and also added at the end of the function:

B4X:
StopMessageLoop

after its done i call again:

B4X:
StartMessageLoop

the important thing is NOT TO RUN A ASYNC METHOD INSIDE THE HANDLER!!

i tried running 50 calls to the server at the same time and all went through and all responded back.

B4X:
for /l %i in (1,1,50) do curl "http://localhost/ai/apitest1?text=בערב קיץ חמים ישב דניאל על ספסל העץ שבקצה החצר והרוח נשאה ריח של יסמין והירח עלה לאט מעל הגגות"

if there is a better solution, could you please upload a simple version how to make async calls to PyBridge?
welcome back @ilan ...b4x is better with company!

websockets with call backs work better for python... but always is how your want your app to works..

b4j combines many technolgies under one package...
 

hatzisn

Expert
Licensed User
Longtime User
I agree that PyBridge is a great library and open many options that were previously difficult to achieve.

@hatzisn the solution for such cases is usually to implement it with async methods that do not block the python process. PyBridge support such methods with Py.RunCodeAwait and Wrapper.RunAwait.

Would it be possible to post an example?

If I run it with Await then is this code correct?

B4X:
Wait For (py.RunCodeAwait("DoSomething", Array(sString1, sString2, sString3), sCode)) Complete (lRet As PyWrapper)

While with run code I do this to get the list returned from Python (with Fetch):

B4X:
Wait For (py.RunCode("DoSomething", Array(sString1, sString2, sString3), sCode).Fetch) Complete (lRet As PyWrapper)

The DoSomething sub in Python calls an OnLine http service that answers after some time.
 

ilan

Expert
Licensed User
Longtime User
websockets with call backs work better for python... but always is how your want your app to works..
i though about using websocket but because its not a feature that make sense to use in my scenario because all i do is a get request to the api and return a value i dont need to stay connected so using handler is more the right way in my case.
 

ilan

Expert
Licensed User
Longtime User
Would it be possible to post an example?

If I run it with Await then is this code correct?

B4X:
Wait For (py.RunCodeAwait("DoSomething", Array(sString1, sString2, sString3), sCode)) Complete (lRet As PyWrapper)

While with run code I do this to get the list returned from Python (with Fetch):

B4X:
Wait For (py.RunCode("DoSomething", Array(sString1, sString2, sString3), sCode).Fetch) Complete (lRet As PyWrapper)

The DoSomething sub in Python calls an OnLine http service that answers after some time.
it should look like this:


B4X:
Sub Handle(req As ServletRequest, resp As ServletResponse)
    resp.ContentType = "application/json; charset=utf-8"
   
    Dim action As String = req.RequestURI.ToLowerCase
    If action.EndsWith("/test") Then
        Dim txt As String = req.GetParameter("text")
        If txt.Length = 0 Then
            resp.Write("{""error"":""missing text""}")
            Return
        End If
        runTest(txt,resp)
        StartMessageLoop
    Else
        resp.Write("{""error"":""unknown endpoint""}")
    End If
End Sub

Sub runTest(txt As String,resp As ServletResponse)
    Dim pyw As PyWrapper = test1(txt)
    Wait For (pyw.Fetch) Complete (Result As PyWrapper)
    Dim jg As JSONGenerator
    jg.Initialize(CreateMap("text":txt))
    resp.ContentType = "application/json; charset=utf-8"
    resp.Write(jg.ToPrettyString(2))
    StopMessageLoop
End Sub
 
Sub test1(txt As String) As PyWrapper
    Dim code As String = $"
def test1(text):
    return text
"$
    Return Main.Py.RunCode("test1",Array(txt),code)
End Sub

i am including a example project and you can try. i have also tested in CMD and all requests went trough


1784453550330.png



1784453676506.png
 

Attachments

  • pybridge server example.zip
    1.8 KB · Views: 149

Erel

B4X founder
Staff member
Licensed User
Longtime User
Two important links about servers and PyBridge:

 

ilan

Expert
Licensed User
Longtime User
thank you erel for the examples. they are very useful. i dont need websocket in my web api. all calls are done to handlers. is my solution (example in post #8) correct? can i use it like this? (it works but i am not sure its the correct way to do it)
 

hatzisn

Expert
Licensed User
Longtime User
Two important links about servers and PyBridge:


The first I have tried it in the past but the second I have not. Quite Impressive.
I tried to find "Await" in both examples but I could not find it. Can you please post also an example with RunCodeAwait.

Maybe when I return home I will try it with my code to check it.
 

ilan

Expert
Licensed User
Longtime User
The first I have tried it in the past but the second I have not. Quite Impressive.
I tried to find "Await" in both examples but I could not find it. Can you please post also an example with RunCodeAwait.

Maybe when I return home I will try it with my code to check it.
check also post #8 this may solve your issue
 

hatzisn

Expert
Licensed User
Longtime User

Erel

B4X founder
Staff member
Licensed User
Longtime User
Your solution is not 100% correct. It will fail if multiple calls are made concurrently. Remember that with jServer requests are handled concurrently (in release mode).

The safe solution is to use a background worker that owns and manages PyBridge. Other handles call it with CallSubDelayed and wait for its response.

For simple cases, you can configure the handler to be a single thread handler: srvr.AddHandler("/test/*", "testHandler", True), but this is not scalable.
 

ilan

Expert
Licensed User
Longtime User
Your solution is not 100% correct. It will fail if multiple calls are made concurrently. Remember that with jServer requests are handled concurrently (in release mode).

The safe solution is to use a background worker that owns and manages PyBridge. Other handles call it with CallSubDelayed and wait for its response.

For simple cases, you can configure the handler to be a single thread handler: srvr.AddHandler("/test/*", "testHandler", True), but this is not scalable.
This is the problem i am facing now. Everything works in debug mode but in release it doesnot work. Stopmessageloop ends the server and without it it even doesnot work in debug mode.

What would be the right way to do using handlers and not websocket?
 

Magma

Expert
Licensed User
Longtime User
This is the problem i am facing now. Everything works in debug mode but in release it doesnot work. Stopmessageloop ends the server and without it it even doesnot work in debug mode.

What would be the right way to do using handlers and not websocket?
why not combine them ?
 

josejad

Expert
Licensed User
Longtime User
The only caveat is if the python code has long processing time you cannot implement it easily in a WebApp because the calls are sequential.

The safe solution is to use a background worker that owns and manages PyBridge. Other handles call it with CallSubDelayed and wait for its response.

I think this thread is becoming something that deserves a place in the B4J [PyBridge] forum
 
Top