Not able to reference local WSDL file when using PEX

628 Views Asked by At

I have a question about pex build. So we have this project structure and we are trying to build a pex file off of it. It has a WSDL file which needs to be referenced in the code. No matter what I do, when I run the pex file, it throws an exception: File Not Found . Does anyone have any idea how to fix it? I am fairly new to Python.

Below is the folder structure -

Main_Folder
  Util
    util1.py
      main.py
        WebService.xml

I tried this:

path = os.path.join(os.path.abspath(__file__), 'WebService.xml')
url = urllib.parse.urljoin('file:', urllib.request.pathname2url(os.path.abspath(path)))
2

There are 2 best solutions below

3
AzyCrw4282 On

Welcome to StackOverflow. As the error indicates, the path is not set correctly.

os.path.abspath(__file__) -> Gives you the absolute path of the file. If I run this code from a file named main.py I get the following output.

C:\Users\User1\Desktop\main.py

Example of os.path.join

# Path 
path = "/home"

# Join various path components  
print(os.path.join(path, "User/Public/", "Documents", ""))

Outputs

/home/User/Public/Documents/-> As you can see it joins the directories.

So you should now be able to see the problem you have. You path variable will hold something like this C:\Users\User1\Desktop\main.py\WebService.xml

So just change it to this `path = os.path.abspath('WebService.xml')

You can read more about the os module here

1
soapergem On

From what I can tell, you need to do three things to be able to utilize static file resources within a PEX deployment package:

  1. Make sure you initially build the PEX package with the --not-zip-safe option,
  2. Forcibly install the setuptools pip package when initially building your PEX package, and
  3. Utilize the pkg_resources module from setuptools to determine the right path to access your resources.

So in order to build your PEX package, you'll need a requirements.txt file that includes at least this line:

setuptools==49.2.0  # or whatever version, really, as long as some version is present

Then build the PEX file with something like this:

# first build the pex file with whatever pip requirements are needed
pex -r requirements.txt -e 'main:main' -o mypexfile.zip --not-zip-safe

# then add your files to it
zip mypexfile.zip Util/util1.py main.py WebService.xml

# finally, rename the extension (not strictly necessary)
mv mypexfile.zip mypexfile.pex

Finally, inside your main.py file, you'll need code like this to access the resource file:

import os
import pkg_resources


def main():
    path = pkg_resources.resource_filename(__name__, "WebService.xml")
    if os.path.exists(path):
        print("file exists")

That call to pkg_resources.resource_filename basically is a way of looking up the ephemeral/relative path to where the file actually lives. If you print out the value of path you'll see it will look funny and unpredictable. For example, in my case it ended up resolving to this value:

/root/.pex/code/da39a3ee5e6b4b0d3255bfef95601890afd80709/WebService.xml

But whatever that value actually is, the point is that the result of that call to pkg_resources.resource_filename will give you the correct path, which should allow you to freely access your resource file.