argcomplete
argcomplete copied to clipboard
Interaction between scripts that both use argcomplete
I'm leaving this here mostly for posterity, as this issue don't seem to have been encountered (or at least written down) before, and hopefully it will save someone the hours of debugging that I've just been through!
I am writing a CLI tool that spawns a subprocess (via subprocess.run
) early on in its init phase, before the parser construction is finished.
The subprocess is a call to ansible-inventory
, which itself happens to use argcomplete
.
As a result argcomplete.autocomplete
is called in the child process before it is called in the parent.
By default, all the subprocess.Popen
wrappers copy os.environ
verbatim to the child process, including _ARGCOMPLETE=1
if present. Of course the child doesn't have an fd8
, so the child exits with return code 1
.
The parent (in our case) raises an exception on the non-zero return from the child, and bang everything breaks.
The debug output contains no indication that the Unable to open fd 8 for writing, quitting
message is actually being emitted by a different process, so piecing this together is not trivial!
The workaround, if you encounter this, is to strip all the completion-specific environment vars before the subprocess
call:
def foo():
...
env = {k: v for k, v in os.environ.items()
if not (k.startswith("COMP_") or
k.startswith("_ARGCOMPLETE") or
k == "IFS")}
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, env=env)
...
I'm not sure that there is an easy fix for this within argcomplete
.
Perhaps another environment variable that indicates the executable being completed? The above fix is easy enough now that I understand what's going on ;-)