<#20206 How To Run a Python Source That Uses Files...
# github-notifications
c
#20206 How To Run a Python Source That Uses Files In Repo Subdirectory New discussion created by justicefreed I'm likely missing something, but more or less, no matter what I do, pants seems to be running my scripts from repo root, without relocated_files targets present. Repo Structure (Monorepo):
Copy code
repo-name
      pants.toml
      -- projects
                -- myservice
                          BUILD
                          config.json
                          -- src
                                    main.py   # imports mylibrary.foo, usually run from myservice dir
                -- myotherservice
                          BUILD
                          otherconfig.json
                          -- src
                                    othermain.py   # also imports mylibrary.foo
      -- library
                -- mylibrary
                          BUILD
                          -- mylibrary
                                   foo.py
The key idea is that
config.json
contains necessary data for `main.py`'s service, but is NOT bundled/deployed with the service and will be different for every deployment instance. This data is loaded via python, using
open("config.json")
. In the deployment context, each project/service lives in it's own somewhat isolated directory, and does not have any sense of the repo structure other than below the
myservice
directory. The goal is to deploy/distribute each service using PEX files. This all generally seems to work. However, I want to be able to use pants to run main.py during development/testing, without breaking the script's access to
config.json
. This is what I can't seem to make work. I've tried: • Using
files
and
relocated_files
to specify that
config.json
should be moved to root at runtime, along with
run_goal_use_sandbox=True
. The file gets successfully added to the sandbox, but running
os.listdir()
and
os.getcwd()
within my script show that the script's working directory is project root, NOT the sandbox as expected. • Same thing except using
pex_binary
instead of
python_source
. Same result. • Using
adhoc_tool
->
run_shell_command
as a hack to try to execute the script using
myservice
as the working directory, but really doesn't seem to be the right approach (though it's nice to be able pass in the default required args that way). At this point, my main question is - why doesn't the python script's working directory use the sandbox directory when that setting is applied? It seems this would resolve my issue. Secondarily, is there any way to run a target with the working directory equal to the BUILD file location for that target? This would be so, so much simpler for my use case I think, but I could not find any way to change the working directory in a way that doesn't break normal, deployed operation. I feel it's likely I'm missing something silly here, so any guidance on how to allow a simple relative file import to work as expected from a script & file with paths relative to their common subdirectory instead of root would be greatly appreciated. I've spent probably 6 hours with the docs trying to get this one thing working 😅 so I've been as thorough as I could. Note: this repo is all on python 3.12, and would not install on the latest stable release, hence the alpha.
pants.toml
Copy code
[GLOBAL]
# pants_version = "2.18.0"
pants_version = "2.19.0a0"
backend_packages = [
    "pants.backend.shell",
    "pants.backend.python",
    # "pants.backend.experimental.python.lint.ruff",
    "pants.backend.python.typecheck.mypy",
    "pants.backend.experimental.adhoc"
]
pants_ignore=["!__pycache__/","!**/__pycache__/","!config.json"]

[source]
root_patterns = [
    '/',
    '/components/*',
    '/library/*',
    '/library-stubs/*',
    '/tools'
]

[python]
interpreter_constraints = ['==3.12']
enable_resolves = true
default_run_goal_use_sandbox = true
myservice -> BUILD
Copy code
python_requirements(
    name="reqs",
    source="requirements.txt",
)

files(
    name="files_needed_at_cwd",
    sources=["dynamic_config_overrides.json"]
)

relocated_files(
    name="cwd_files",
    src="components/MTConnectClient",
    dest="",
    files_targets=[":files_needed_at_cwd"]
)

pex_binary(
    name="pex_binary",
    entry_point="main",
    dependencies=[":cwd_files"]
)

python_source(
    name="main",
    source="src/main.py",
    dependencies=[":reqs",":cwd_files"],
    run_goal_use_sandbox=True
)
pantsbuild/pants