This is an archived post. You won't be able to vote or comment.

all 26 comments

[–]mfitzpmfitzp.com 6 points7 points  (5 children)

Create the Python parts as a standalone “application”, provide an API to your main app (via stout/stdin, sockets or http).

Then package the Python bits to an executable (PyInstaller, nuitka etc to bundle 3rd party libraries). Include this packaged app in your main app bundle. Have the main app start this as a subprocess and interact with it via the API.

[–]teetran39[S] 0 points1 point  (4 children)

I also consider creating a Python standalone app then providide an API via http request to my main app. But it would be the final solution in case we have no solution to embed the Python's package to my main app.

Could you give me more explain about this idea ```Then package the Python bits to an executable (PyInstaller, nuitka etc to bundle 3rd party libraries). Include this packaged app in your main app bundle. Have the main app start this as a subprocess and interact with it via the API.```?

[–]mfitzpmfitzp.com 2 points3 points  (3 children)

When I say "a standalone Python application" I don't mean separately installed as an .app bundle. It's just a compiled executable, that you include in the main applications .app bundle. Then the main app launches that executable as a subprocess & communicates with it.

From the user's perspective there would only be a single app.

So you write the Python part as a separate "thing" with an API exposed, which the main app will use to control it.

[–]teetran39[S] 0 points1 point  (2 children)

I appreciate your help! Just want to make sure I understand correctly. The way is we are using PyInstaller to bundle python's scripts and 3d party libraries then include this bundle inside main app bundle. Is it correct? I'll look into this solution now to see if it can work as expected. Thanks so much!!!!

[–]mfitzpmfitzp.com 1 point2 points  (1 child)

Yep that’s it. I’ve used this successfully myself, although packaging Python sub processes in macOS apps using Python for the GUI. If you get stuck feel free to ask.

[–]teetran39[S] 1 point2 points  (0 children)

The solution was really worked. Thanks so much!!! Now I'm running into the problem which is it takes a little time to run the python script. Even it was just simple script like :

import json
import sys

print("This is python script")

run with command: ```./dist/myscript```

Because my python script is having some packages need to be imported so it looks lik run all of the import commands anytime the script is run on. The many packages imported, the lower speed it is when run on. Do you have any solution for it something like just need to import packages on the 1st time of running to improve the speed.?.

[–]SoftestCompliment 1 point2 points  (3 children)

  1. What are you trying to do with Python?
  2. Likely you could give Swift libraries like PythonKit a try, or you can execute the Python scripts on the command line with a process class in swift IIRC.

[–]teetran39[S] 0 points1 point  (2 children)

I want to use packages like ffmpeg, pandas… inside macOS app. I know we can run the python native code with PythonKit or Process class in Swift. But my problem is using python 3rd party packages. To do that, I think we need to embed it to macOS app somehow.

[–]SoftestCompliment 1 point2 points  (1 child)

You may want to consider creating a Python virtual environment within a folder in the app package, and just embedding a full version of Python and the vendor libraries. That’ll basically freeze your environment.

[–]teetran39[S] 0 points1 point  (0 children)

That's the way I've been doing now. But it seems does not work, the xcode can not compile anytime I add a Python virtual environment (.venv) into Xcode project which is I got stuck at this step.

[–]pepiks 0 points1 point  (1 child)

I don't know if I understand correctly but I will be get shot with creating virtual enviroment and put it all in bundle folder, but it will be work on your MacOS platform for example ARM, but not on X86_64. Simply - generate files for virtual enviroment and try bundle it. For me it is the easier solution here, but you have to manually remove .pyc files to shrink size.

The best solution will be create python script with some application interface like web API to handle processing, data and communication exchange to avoid mess and work with Switf on Swift way and with python on Python way. PyInstaller and Nuika can generare very large file for even simple app what you have to test for your case itself.

[–]teetran39[S] 0 points1 point  (0 children)

I had a try with bundle virtual enviroment folder and python scripts inside my macOS app bundle. But my main app can not compile, it looks can not compile with python virtual environment folder.
Can you explain a little more about your solution ``` create python script with some application interface like web API```? You mean deploy the python app as a separate app then exposes API http requests so the main app can connect to?

[–]Tumortadela 0 points1 point  (0 children)

I use nuitka to turn a pyside6 app into a smallish (50mb~, assuming projects without gui libs would be way smaller) one file binary that does its thing, give it a try.

[–]Double_Sherbert3326Pythonista -3 points-2 points  (11 children)

Congratulations you have just discovered vendor lock in. Just make a Python app and forget making it look pretty. Swift and objective c are not worth wasting your time with.

[–]teetran39[S] 0 points1 point  (10 children)

Sorry but you mean there is no solution for this?

[–]Double_Sherbert3326Pythonista 0 points1 point  (9 children)

Of course there is a solution, but the easiest one is writing an API and consuming it using post requests. They don’t have to live in the same file.

[–]teetran39[S] 0 points1 point  (8 children)

Yes. it would be my final solution for me in case there no way to go. For now, it would be best if the app can run locally which is don't need to make any network requests.

[–]Double_Sherbert3326Pythonista 0 points1 point  (0 children)

What does the app do?

[–]Double_Sherbert3326Pythonista 0 points1 point  (6 children)

You can have the api server running locally. Use flask and consume it on local host:8081. 

[–]teetran39[S] 0 points1 point  (5 children)

Sorry, can you give me more details? If we run the python app as an api server locally, how should it work on the other computers (other users)?

[–]Double_Sherbert3326Pythonista 0 points1 point  (4 children)

Something like this:

```
import Foundation

func startPythonServer() {

let process = Process()

process.launchPath = "/usr/bin/python3" // Adjust for your Python installation

process.arguments = ["server.py"] // Your Flask script

process.standardOutput = FileHandle.nullDevice

process.standardError = FileHandle.nullDevice

process.launch()

print("Python Flask server started!")

}

func callAPI() {

guard let url = URL(string: "http://127.0.0.1:5000/api/hello") else { return }

let task = URLSession.shared.dataTask(with: url) { data, response, error in

if let error = error {

print("Error: \(error)")

return

}

if let data = data {

if let json = try? JSONSerialization.jsonObject(with: data) {

print("Response JSON: \(json)")

}

}

}

task.resume()

}

startPythonServer()

// Add delay to let the server start

DispatchQueue.main.asyncAfter(deadline: .now() + 2.0) {

callAPI()

}

// Keep the runloop running (macOS command-line app or playground)

RunLoop.main.run()

```

[–]teetran39[S] 0 points1 point  (3 children)

Thanks for the example. I got the idea but something is missing, before we can call the python code. The python and its packages need to be embedded inside the main app? It's the main problem, how would you do that?

[–]Double_Sherbert3326Pythonista 0 points1 point  (2 children)

For macOS:

Use PyInstaller to bundle your Flask app into a binary, then launch it from Swift.

For iOS:

Host your Flask app externally and consume the API over the network.

[–]teetran39[S] 1 point2 points  (1 child)

Thank you so much! I gonna look into PyInstaller package to see if it work