beeware / Python-Apple-support

A meta-package for building a version of Python that can be embedded into a macOS, iOS, tvOS or watchOS project.
MIT License
1.08k stars 155 forks source link

Unable to work with PythonKit #198

Closed nishant-dani closed 6 months ago

nishant-dani commented 6 months ago

Describe the bug

I have followed the instructions to use PythonKit alongside the python-stdlib and lib-dynload, After setting up the environment variables for PYTHONHOME and PYTHONPATH to point to the right locations, the PythonKit initialize function (Py_Initialize()) is failing with this error. I had to adjust the settings for using it in a swift package that is loaded as part of the application and also had to adjust for XCTest to make sure it can use the right bundle. This is the code and I have verified that the path exists.

        var stdLibPath: String?
        var bundle: Bundle = Bundle.main
        stdLibPath = bundle.path(forResource: "python-stdlib", ofType: nil)
        if stdLibPath == nil {
            print ("Unable to find python-stdlib in bundle resources \(bundle.resourcePath)")

            bundle = Bundle(for: EipohubLib.self)
            print("\(bundle.resourcePath)")
            stdLibPath = bundle.path(forResource: "python-stdlib", ofType: nil, inDirectory: "eipohublib_eipohublib.bundle/Contents/Resources")

            if stdLibPath == nil {
                print ("Unable to find python-stdlib in bundle resources \(bundle.resourcePath) inDirectory eipohublib_eipohublib.bundle/Contents/Resources")
                return
            }
        }

        var libDynloadPath: String?
        bundle = Bundle.main
        libDynloadPath = bundle.path(forResource: "python-stdlib/lib-dynload", ofType: nil)
        if libDynloadPath == nil {
            print ("Unable to find python-stdlib/lib-dynload in bundle resources \(bundle.resourcePath)")

            bundle = Bundle(for: EipohubLib.self)
            libDynloadPath = bundle.path(forResource: "python-stdlib/lib-dynload", ofType: nil, inDirectory: "eipohublib_eipohublib.bundle/Contents/Resources")

            if libDynloadPath == nil {
                print ("Unable to find python-stdlib/lib-dynload in bundle resources \(bundle.resourcePath) inDirectory eipohublib_eipohublib.bundle/Contents/Resources")
                return
            }
        }

        setenv("PYTHONHOME", stdLibPath!, 1)
        setenv("PYTHONPATH", "\(stdLibPath!):\(libDynloadPath!)", 1)
        print ("PYTHONHOME is ", String(utf8String: getenv("PYTHONHOME")!))
        print ("PYTHONPATH is ", String(utf8String: getenv("PYTHONPATH")!))

        // Temporarily disable Python
        Python.Py_Initialize()
        print ("Py_Initialize complete")

PythonKit/PythonLibrary.swift:59: Fatal error: 'try!' expression unexpectedly raised an error: Python library not found. Set the PYTHON_LIBRARY environment variable with the path to a Python library.

If I set the PYTHON_LIBRARY to point to the python-stdlib folder, it fails because PythonKit is trying to do dlopen and expects the path to point to a .so file.

Any guidance on how to progress further, to make sure I can hook up PythonKit?

Steps to reproduce

  1. Go to '...'
  2. Click on '....'
  3. Scroll down to '....'
  4. See error

Expected behavior

Expected to have PythonkIt initialize with and invoke a python import call.

Screenshots

No response

Environment

I am using the following dependencies for my target

dependencies: [
    // 💧 A server-side Swift web framework.
    .package(url: "https://github.com/apple/swift-nio.git", from: "2.58.0"),
    .package(url: "https://github.com/apple/swift-atomics.git", from: "1.0.2"),
    .package(url: "https://github.com/pvieito/PythonKit.git", .branch("master")),
    .package(url: "https://github.com/apple/swift-log.git", from: "1.0.0")
],

Logs

Additional context

No response

nishant-dani commented 6 months ago

Closing this issue, as it is no longer needed. The problem was that the incorrect Py_Initialize was being called from import PythonKit instead of import Python.