'bazel run from a running py_binary
I've got a py_binary and another runnable target. I want to bazel run //:the_inner the second target (which could be a py_binary as well) from the first target bazel run //:the_outer
py_binary(
name="the_outer",
srcs=["the_outer.py"]
)
py_binary(
name="the_inner",
srcs=["the_inner.py"]
)
A simple
rv = subprocess.run( "bazel run //:the_inner".split(), capture_output=True, text=True)
Gives me a error message, telling me I shouldn't do this and tells me the workspace I should have used. At this point I just parse the error message and call the second target again.
workspace = re.search( r"'(\.\w/)+'". rv.stderr ).group(1)
subprocess.run( "bazel run //:the_inner".split(), cwd=workspace)
It works, but the solution is extremly awkward. Is there a canonicial way of bazel running stuff from another bazel run, particularly for python?
Solutions I have seen include
- resolving the symlinks in the sandbox and hoping you end up in the workspace
find / -name WORKSPACEand hoping there is only one- wrapping everything in a shell script and passing
bazel info workspaceas a parameter
No, it shouldn't be done. No don't care - not if there are so many simple workarounds
Solution 1:[1]
I found what I was looking was in the docs: https://docs.bazel.build/versions/main/user-manual.html#run
subprocess.run( "bazel run //:the_inner".split(), cwd=os.environ.get("BUILD_WORKSPACE_DIRECTORY","."))
extra environment variables are also available to the binary:
- BUILD_WORKSPACE_DIRECTORY: the root of the workspace where the build was run.
- BUILD_WORKING_DIRECTORY: the current working directory where Bazel was run from.
Solution 2:[2]
The more typical approach is for the "outer" binary to depend on the "inner" binary via "data", and use the python runfiles library to find the inner binary.
https://github.com/bazelbuild/bazel/blob/master/tools/python/runfiles/runfiles.py
For example:
BUILD:
py_binary(
name = "a",
srcs = ["a.py"],
deps = ["@bazel_tools//tools/python/runfiles:runfiles"],
data = [":b"],
)
py_binary(
name = "b",
srcs = ["b.py"],
)
a.py:
from bazel_tools.tools.python.runfiles import runfiles
import subprocess
r = runfiles.Create()
rv = subprocess.run(r.Rlocation("__main__/b"), capture_output=True, text=True)
print("b says:")
print(rv.stdout)
b.py:
print("hello world")
running:
$ bazel run a
INFO: Analyzed target //:a (39 packages loaded, 296 targets configured).
INFO: Found 1 target...
Target //:a up-to-date:
bazel-bin/a
INFO: Elapsed time: 0.791s, Critical Path: 0.01s
INFO: 8 processes: 8 internal.
INFO: Build completed successfully, 8 total actions
INFO: Build completed successfully, 8 total actions
b says:
hello world
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | gnight |
| Solution 2 | ahumesky |
