I'm a little confused about `shell_command`. Why c...
# general
e
I'm a little confused about
shell_command
. Why can't I run it using
pants run :mycommand
? I need to use this instead of
run_shell_command
because the latter doesn't run the command inside pants' sandbox.
c
The general philosophy of
pants run
is that it's for things that happen inside of the current workdir. So
run_shell_command
would be for things that you want to run in the workdir (eg maintenance commands and utilities).
shell_command
is intended for steps that are part of the build process, which is why it has
output_files
and
output_directories
. Our doc on running shell commands is a little thin; please let us know how we can improve it!
s
PS to run the
shell_command
and produce output files use
export-codegen
goal
e
Thank you, both! What is the preferred method for running dev commands inside a sandbox? I'm using mprocs to run a flask dev server (dependent on pip packages in the sandbox), a react-router dev server, and caddy, which means I can't directly call a python file (or anything like that). Is there any other way to achieve this, or do I need to use
export-codegen
during development? Semantically, it doesn't make a lot of sense. I guess another option would be to use
run_shell_command
+ sourcing the exported python venv, but that would include all dependencies (instead of the ones connected with
execution_dependencies
). Eventually, it would be cool to have some kind of sandbox option on
run_shell_command
... just a thought.
Yes @careful-address-89803, it would be nice to have something like "`shell_command` is intended for use during the build process. For that reason, it cannot be invoked using the
pants run
goal. If you need to run it without starting the build process, use the
pants export-codegen
goal"
s
the idea behind the
shell_command
is that it is not supposed to have side effects. For example, you have a text file in pants and you want to produce a new file by filtering rows with
grep
, this is what you do with a
shell_command
. Similarly,
adhoc_tool
is used for the same kind of thing but is more powerful, because it can run any runnable target, e.g. you can build a python pex then run it to produce a new output file. If you want some sort of side effect, you need to use something else like
run_shell_command
or maybe
docker_image
or just manually run a shell script
e
Just tried
export-codegen
. Because my command is a dev server, expects user interaction, and doesn't produce any files. It just exited without running the server...
So there's no great way to reduce the number of deps (i.e. I need to load the python venv)?
s
So there's no great way to reduce the number of deps (i.e. I need to load the python venv)?
I'm not sure I understand the question
you don't need to source the venv in order to run things in the venv
e
There are python libraries that I need access to for my command to work. I could access them by loading an exported python venv, but I can't think of any other way that would reduce the number of deps that need to be installed
By source I mean
source venv/bin/activate
...activate would be a better word
s
in pants the idea is to use something like a
pex_binary
, it will include all necessary dependencies without problems with venvs
e
...so I'd need to create a pex_binary for the flask dev server, then run it using flask? I'm not quite sure how to execute that, but I could try
The flask server itself is executed by the
flask --app main --debug run
command, so I'd have to convert that into a standalone python file somehow
s
you can run it from code
flask.run(debug=True)
e
That should work.
But and issue I'm anticipating: pants only lets you run one command at a time, right? If I need to run multiple python servers, would I need to use a python based multiplexer, or would it still be possible to use mprocs?
s
Copy code
# run.py
from flask import Flask

app = Flask(__name__)


@app.route("/")
def hello_world():
    return "<p>Hello, World!</p>"


if __name__ == "__main__":
    app.run(debug=True)
Copy code
# pants.toml
[GLOBAL]
pants_version = "2.23.0"
backend_packages = [
  "pants.backend.python",
]

[python]
enable_resolves = true
default_resolve = "python-default"
interpreter_constraints = [">=3.12,<3.13"]
Copy code
# BUILD
python_requirement(name="flask", requirements=["flask"])
python_sources()
pex_binary(name="app", entry_point="run.py")
e
I can't compile to a binary at this stage because that would mess up hot-reloading
s
Copy code
$ pants run :app
 * Serving Flask app 'run'
 * Debug mode: on
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
 * Running on <http://127.0.0.1:5000>
Press CTRL+C to quit
 * Restarting with stat
 * Debugger is active!
 * Debugger PIN: 782-899-796
e
thanks for the detail, by the way, I appreciate it
s
But and issue I'm anticipating: pants only lets you run one command at a time, right?
If I need to run multiple python servers, would I need to use a python based multiplexer, or would it still be possible to use mprocs?
That's a good question, short answer is yes, pants doesn't have tools to run multiple things at once
In general from my own experience pants is not very friendly in the development process. Many things are hidden, e.g. you can't easily see interactive docker build logs, pexes builds are slow, dependency inference in large repos is slow. However, pants is pretty nice in CI and production, it makes sure you run all the linters, deploy all the targets, makes it pretty stable. So my advice here is to use something else for local development, e.g. I started heavily using uv along with pants
e
Okay, I'll check it out. Thanks!