I'm trying to create a pex for a python CLI script...
# general
I'm trying to create a pex for a python CLI script in pants 2.15 (upgrading from 1.30), and if I use the
tag in my build file for the pex binary then pants complains that it cannot find the file that's in the same directory as the build file. If I use the
tag I get an import error saying there was no module main found. I'l curious to see what I could be doing wrong
If it's helpful, the cli uses an async main method as well
field is for console scripts - those are generally only defined in a packaged wheel via entry_points.txt metadata. Like so for the
Copy code
$ cat /home/jsirois/.pex/installed_wheels/0b005324b3bd9c50d9214dfd38a39e4bf4522635e32bec351d7dfcd4c9e3e6e2/cowsay-5.0-py2.py3-none-any.whl/cows
cowsay = cowsay.main:cli
That is likely not what you mean.
For the
field, please dump your BUILD here if possible.
And - wow! I'm not sure I'm aware of anyone tackling that big an upgrade.
Yeah, we're more or less forced to do it because I couldn't figure out how to get 1.30 to play nicely with python 3.11. I'll upload the build momentarily
Gotcha. Yeah - its tough to stay on a mix of unmaintained software and latest greatest.
This is a test of the build file I'm trying to make a CLI out of. I used the same format for a micro-service and no matter if it's inside of a docker container or in a local virtual env running python 3.11.2, I get
ImportError: No module named main
Ok, the issue is no target owns main.py. You'd need to add a
python_source(name="main",  source="main.py")
and then add a dep on that in the
Note that a big change in Pants v2 is you can leave off every explicit dependency that is resolvable by parsing Python import statements.
So you can probably ditch all those 3rdparty deps.
At the very least.
Oh, I'll add a source like that. Let me give that a shot locally and see if I can get things working
So, idiomatically now you'd have:
Copy code
pex_binary(name="shorts", entry_point="main.py:runner")
And all the rest would be done for you assuming main.py tranisitively imported all the rest and all the rest had BUILD files with python_source(s) targets owning them.
If you haven't seen
pants tailor
, that's new and deals with populating these ~empty BUILD targets. Pants can infer most things now, but it still - weirdly - needs empty targets at least to own files. Pure legacy weirdness. + https://www.pantsbuild.org/docs/reference-tailor + https://www.pantsbuild.org/docs/initial-configuration#generate-build-files
Using tailor is not as impactful with pre-existing BUILD files. You'd basically have to delete some BUILD files, then run
pants tailor ::
, then adjust.
But that might be one way to trim the fat during or after the upgrade.
Yeah, I'm at a weird spot where I'm cutting code over to pants 2.15 while also maintaining the 1.30 pipeline. Not wanting to do all or nothing changes
I now have this but am getting redirected to python terminal instead of executing the CLI script
Can you add a very early
to main.py and then provide full output for
pants run ...
assuming that's the goal you are running here. If not and it's
pants package ... && ./dist/shorts.pex
- then same.
If it's helpful, the cli uses an async main method as well
You'll have to excuse my ignorance. I thought you needed a normal main entry point that started an event loop to then get into async-land. Perhaps revealing as much of the main.py as you can would be helpful.
I don't think the async part matters. I ran the run command and got an import error from a first party module that makes sense to me. So I think I'm good to go
Ok - great.
Just to close the loop here. I was able to get the menu I expected from my CLI when I did a pants run command. Thanks for the help this morning!
Excellent. And thanks for closing the loop.