Facing a new issue: when trying to build a pex bin...
# general
s
Facing a new issue: when trying to build a pex binary pants is not respecting the interpreter constraints and building it with a different version of python, resulting in this error when I try to run the docker container:
Copy code
ResolveError(
pex.environment.ResolveError: Failed to resolve requirements from PEX environment @ /root/.pex/unzipped_pexes/1bc1b3d05270a6cb192aecf5a51715e951da993c.
Needed cp39-cp39-manylinux_2_31_x86_64 compatible dependencies for:
 1: MarkupSafe>=2.0
    Required by:
      FingerprintedDistribution(distribution=Jinja2 3.1.1 (/root/.pex/installed_wheels/0893af5400986fb3b6c0f06db963e45dd7e2e9be91f476133910371878af80e8/Jinja2-3.1.1-py3-none-any.whl), fingerprint='0893af5400986fb3b6c0f06db963e45dd7e2e9be91f476133910371878af80e8')
    But this pex had no 'MarkupSafe' distributions.
in `pants.toml`:
Copy code
[python]
interpreter_constraints = ["CPython==3.9.10"]
debug logs when running `./pants package src/app/Dockerfile --level=debug`:
Copy code
10:39:20.62 [DEBUG] Completed: Find Python interpreter for constraints - Selected /Applications/Xcode.app/Contents/Developer/Library/Frameworks/Python3.framework/Versions/3.8/bin/python3.8 to run PEXes with.
e
That last snip is really not enough to go on. Pants, for example, searches not just for your required interpreter, but also for its own to do internal things, like run the Pex tool with (you can run the Pex tool with any Python interpreter from 2.7, and 3.5+ even when generating a PEX file with it that targets some other interpreter completely). Can you provide full detail from the debug log?
Yeah, "... to run PEXes with." is simply a lie. We were trying to be too helpful with that message but its in the wrong context. We emit it for any search for a Python interpreter whether its to tunr the Pex CLI with, to run a PEX with, or for any other purpose.
s
oh, makes sense
later in the logs it seems to be using the correct version of python though 🤔
Copy code
11:12:03.50 [DEBUG] Completed: Find interpreter for constraints: CPython==3.9.10
11:12:03.50 [DEBUG] Completed: Scheduling: Find interpreter for constraints: CPython==3.9.10
11:12:03.50 [DEBUG] Completed: Find Python interpreter for constraints - Selected /Users/demoda/.pyenv/versions/3.9.10/bin/python3.9 to run PEXes with.
11:12:03.50 [DEBUG] Completed: Hit: Local cache lookup: Determine Python imports for src/hasura_webhooks_proxy/app.py
11:12:03.50 [DEBUG] Completed: Scheduling: Determine Python imports for src/hasura_webhooks_proxy/app.py
11:12:03.51 [DEBUG] Completed: pants.backend.python.util_rules.python_sources.prepare_python_sources
11:12:03.52 [DEBUG] Completed: Hit: Local cache lookup: Building local_dists.pex
11:12:03.52 [DEBUG] Completed: Scheduling: Building local_dists.pex
11:12:03.52 [DEBUG] Completed: pants.backend.python.util_rules.pex.build_pex
11:12:03.52 [DEBUG] Completed: pants.backend.python.util_rules.python_sources.strip_python_sources
11:12:03.52 [DEBUG] Completed: pants.backend.python.util_rules.pex_from_targets.create_pex_from_targets
11:12:03.52 [DEBUG] Completed: Hit: Local cache lookup: Building src.hasura_webhooks_proxy/app.pex with 1 requirement: flask==2.1.1
11:12:03.52 [DEBUG] Completed: Scheduling: Building src.hasura_webhooks_proxy/app.pex with 1 requirement: flask==2.1.1
11:12:03.52 [DEBUG] Completed: pants.backend.python.util_rules.pex.build_pex
11:12:03.52 [DEBUG] Completed: pants.backend.python.goals.package_pex_binary.package_pex_binary
11:12:03.52 [DEBUG] Did not build any upstream Docker images
11:12:03.52 [DEBUG] Built packages for Docker image: src.hasura_webhooks_proxy/app.pex
e
Thanks. Ok, backing up a bit. You're on Mac trying to build a PEX for Linux (to be used in a Docker image). Is that PEX file defined by a
pex_binary
target that sets platforms or complete_platforms?
s
just this:
Copy code
pex_binary(
    name="app",
    entry_point="app.py",
)
e
That's the problem then.
s
ohhhh, I get it
I should add
linux-x86_64
right?
e
No, you need to read some more docs there. Just a sec...
The easiest way to find out the exact platform string needed is, in your docker image, run this:
Copy code
/path/to/my/python -mvenv pex.venv
pex.venv/bin/pip install pex
pex.venv/bin/pex --help
In the
pex --help
you're looking for the
--platform
help which will have a line like:
Copy code
For the current interpreter at /home/jsirois/.venv/pex/bin/python3 the full platform string is manylinux_2_35_x86_64-cp-3.10.2-cp310.
That should save a lot of trouble guessing.
The next problem you can hit is when the resolve for your PEX includes distributions that are only available in source form (.tar.gz or .zip sdist). For that, neither Pants nor Pex offer cross-building; so you must pre-build those wheels. If you hit this problem, I can explain more. Hopefully you don't though.
r
I've hit this problem... developing on Mac, with a dependency that comes with a source distribution (Quickfix), and building a Docker container to run on Linux. Everything works great on the Mac side of things... can run the binary generated by Pex but when I try to
./pants run Dockerfile
I get a whole bunch of
Copy code
pex.environment.ResolveError: A distribution for quickfix could not be resolved in this environment.Found 1 distribution for quickfix that do not apply:
1.) The wheel tags for quickfix 1.15.1 are cp310-cp310-macosx_12_0_x86_64 which do not match the supported tags of /usr/local/bin/python3.10:
cp310-cp310-manylinux_2_31_x86_64
cp310-cp310-manylinux_2_30_x86_64
cp310-cp310-manylinux_2_29_x86_64
cp310-cp310-manylinux_2_28_x86_64
which makes sense, looking for some guidance on how to resolve.
In our pre-Pants world this is happening with a multi-stage build, which leverages pipenv and a Pipfile to install and build the dependencies. I'd guess I want to do the same thing here, or maybe I need to run Pants inside the container itself as the first stage and not take a dependency on the PEX externally?
From https://www.pantsbuild.org/docs/python-package-goal
PEX files may be platform-specific
If your code's requirements include distributions that include native code, then the resulting PEX file will only run on the platform it was built on.
Yes, unfortunately that is the case for me 😢
e
Yeah, you're looking for https://github.com/pantsbuild/pants/issues/13682 In the past, companies like Twitter and Foursquare solved this case by setting up corporate wheel-building infrastructure such that they always had pure wheels available for all machines targeted. They'd serve this up in a custom find-links repo or in a custom cheeseshop index and then configure
[python-repos]
indexes
or `repos`: https://www.pantsbuild.org/docs/reference-python-repos
One thing to note here. That error you're getting @rapid-exabyte-76685 is very late and it will always happen, even when Linux wheels are available because you have not specified platforms (or, instead
complete_platforms
) for the associated
pex_binary
target. You must use that field to tell Pants to build a multiplatform PEX file that has even a chance of running on Mac and Linux. Once you have platforms specified, the building of the PEX file will fail fast up front if it can't find wheels for every required dependency for each platform you have specified. To get the appropriate platform string for your Docker image, just do something like:
Copy code
$ docker run --rm python:3.10 bash -c '
> /usr/local/bin/python3.10 -mvenv pex.venv
> pex.venv/bin/pip -q install pex
> pex.venv/bin/pex3 interpreter inspect -v -i2
> '
{
  "path": "/pex.venv/bin/python3.10",
  "version": "3.10.4",
  "requirement": "CPython==3.10.4",
  "platform": "manylinux_2_31_x86_64-cp-3.10.4-cp310",
  "venv": true,
  "base_interpreter": "/usr/local/bin/python3.10"
}
The key thing is to use the full path to the interpreter you want to target in the image in that 1st bash script line.
👍 1
r
by setting up corporate wheel-building infrastructure such that they always had pure wheels available for all machines targeted.
yep, agree that's the path I will need to take.