-
Notifications
You must be signed in to change notification settings - Fork 45
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
script() does not accept argument list, only works with valid UTF-8 string #80
Comments
Thanks @gabriel-v for sharing these ideas. I'll need some time to think through some of the implications for backwards compatibility. One thing to keep in mind is that a common use of I do think its very doable to have |
Ah, forgot about
Ah, so that's why it doesn't make sense to support As commented on the other issues, there isn't a problem that can't be solved by staging more files and improvising scripts with
I'm looking to port a codebase to redun that handles its own data loading on workers, and uses And also the valid-UTF8 problem is a very specific one - it makes sense to keep handling it internally in my own codebase until more people complain about it (if ever) |
|
The script() task accepts a single string with the script. It prints that script to a file and uses
subprocess(cmd, shell=True)
to run that file.This is a problem when your arguments need to be escaped for bash - think filenames that contain spaces, quotes, double quotes, and any special bash character you can think of. That means the caller needs to escape all arguments using bash syntax, which is not a simple thing to do.
Subprocess, on the other hand, allows calling processes by argument list, and sends those arguments directly to
execv
and friends, no escape needed.A second limitation of this system is that it assumes the command is valid UTF-8 - this is not always the case, see #79
I propose we add a check for
script(cmd)
ifcmd
is a list. If it is, pass it as a list, untouched, to thesubprocess.run(cmd, shell=False)
. If it's not a list, keep doing what it's been doing.There will be a complication with the intermediary script: could we avoid saving the intermediary script on disk entirely and just run subprocess?
Thinking some more about it, I feel like this script() should be a thin wrapper over the entire
subprocess.run/Popen
API - so instead of staging a bash file that we dump the script in, we stage a pickle of(args, kwargs)
.Instead of running bash, we run something like
python -c "import subprocess, pickle, sys; args, kwargs = pickle.loads(open(sys.stdin)); sys.exit(subprocess.run(*args, **kwargs, stdout=sys.stdout, stderr=sys.stderr).returncode)
.That way, existing scripts will be unchanged (it's still subprocess.run on some text with
shell = True
) - but now you suddenly support all the othersubprocess.run
arguments, likeenv
,cwd
,timeout
that some other issues were asking for (#67).We'd need to make sure this is really backwards compatible, and doesn't break any existing
script()
workflows - I think all we need to do in the pickle packer proposed above is defaultshell
to True instead of False. For safety, we would also want to prevent users from:stderr
orstdout
to anything - we forward thosestdin
to anything - it's probably some PIPE that will not survive execution. users should useinput
argument instead with string or bytestringcapture_output
- same as aboveAnything else should be fair game through.
Or, we just document these limitations and invite users to call
subprocess
themselves - that's perfectly fineThe text was updated successfully, but these errors were encountered: