2

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)))
Rick Smith
  • 3,962
  • 6
  • 13
  • 24
Aks
  • 23
  • 2
  • Did you ever figure this out? – soapergem Jul 09 '20 at 14:55
  • Nope I ended up just unzipping the pex file and then use ```os.path.abspath``` to reference the WebService.xml file. It was much easier than spending more time to just reference the file. – Aks Jul 09 '20 at 23:59
  • Alright I've got this figured out and verified a solution works. I'm going to write up an answer now. – soapergem Jul 17 '20 at 14:33

2 Answers2

0

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

AzyCrw4282
  • 7,222
  • 5
  • 19
  • 35
  • Thanks, I did do that way and it worked when I ran the main.py file directly. Hwoever, if I package the whole thing with pex it is throwing error. Saying it cant find the Webservice.xml because the absolute path is different. – Aks Feb 20 '20 at 16:54
  • I think the problem is since the xml file is zipped inside the pex file it wont let me reference that file. So when I generated the pex from the above directory, it includes all the files. When I am running the pex, it is getting the xml file path as "/users/aks/somefolder_pex_location/webservice.xml". This is where it fails. I am not sure what to do – Aks Feb 20 '20 at 21:15
  • **'I think the problem is since the xml file is zipped inside the pex file it wont let me reference that file'** -> this is not true, it should be able to reference it. You may need to alter the values when running on your system and when generating a pex. Since .xml file is in the same directory as the main.py file, can you try setting the `path = 'WebService.xml'` when generating it and see what that does – AzyCrw4282 Feb 21 '20 at 01:47
0

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.

soapergem
  • 9,263
  • 18
  • 96
  • 152
  • Unfortunately it does not work with your solution. I posted my question [here](https://stackoverflow.com/questions/73457013/how-to-add-properties-file-inside-a-pex-package). Mind taking a look? Basically `pkg_resources.resource_filename` returns an actual path, but the file does not exist, I cannot open it. – payloc91 Aug 23 '22 at 10:28