Run a `cmd_loc` command with the `args` arguments list and return the return code, the stdout and stderr. To avoid RAM exhaustion, always write stdout and stderr streams to files. If `to_files` is False, return the content of stderr and stdout as ASCII strings. Otherwise, retu
(cmd_loc, args, cwd=None, env=None, to_files=False, log=TRACE)
| 46 | |
| 47 | |
| 48 | def execute(cmd_loc, args, cwd=None, env=None, to_files=False, log=TRACE): |
| 49 | """ |
| 50 | Run a `cmd_loc` command with the `args` arguments list and return the return |
| 51 | code, the stdout and stderr. |
| 52 | |
| 53 | To avoid RAM exhaustion, always write stdout and stderr streams to files. |
| 54 | |
| 55 | If `to_files` is False, return the content of stderr and stdout as ASCII |
| 56 | strings. Otherwise, return the locations to the stderr and stdout temporary |
| 57 | files. |
| 58 | |
| 59 | Run the command using the `cwd` current working directory with an `env` dict |
| 60 | of environment variables. |
| 61 | """ |
| 62 | assert cmd_loc |
| 63 | full_cmd = [cmd_loc] + (args or []) |
| 64 | |
| 65 | # any shared object should be either in the PATH, the rpath or |
| 66 | # side-by-side with the exceutable |
| 67 | cmd_dir = os.path.dirname(cmd_loc) |
| 68 | env = get_env(env, lib_dir=cmd_dir) or None |
| 69 | cwd = cwd or curr_dir |
| 70 | |
| 71 | # temp files for stderr and stdout |
| 72 | tmp_dir = get_temp_dir(prefix="cmd-") |
| 73 | |
| 74 | sop = path.join(tmp_dir, "stdout") |
| 75 | sep = path.join(tmp_dir, "stderr") |
| 76 | |
| 77 | # shell==True is DANGEROUS but we are not running arbitrary commands |
| 78 | # though we can execute commands that just happen to be in the path |
| 79 | # See why we need it on Windows https://bugs.python.org/issue8557 |
| 80 | shell = True if on_windows else False |
| 81 | |
| 82 | if log: |
| 83 | printer = logger.debug if TRACE else lambda x: print(x) |
| 84 | printer( |
| 85 | "Executing command %(cmd_loc)r as:\n%(full_cmd)r\nwith: env=%(env)r\n" |
| 86 | "shell=%(shell)r\ncwd=%(cwd)r\nstdout=%(sop)r\nstderr=%(sep)r" % locals() |
| 87 | ) |
| 88 | |
| 89 | proc = None |
| 90 | rc = 100 |
| 91 | |
| 92 | try: |
| 93 | with io.open(sop, "wb") as stdout, io.open(sep, "wb") as stderr, pushd(cmd_dir): |
| 94 | proc = subprocess.Popen( |
| 95 | full_cmd, |
| 96 | cwd=cwd, |
| 97 | env=env, |
| 98 | stdout=stdout, |
| 99 | stderr=stderr, |
| 100 | shell=shell, |
| 101 | # -1 defaults bufsize to system bufsize |
| 102 | bufsize=-1, |
| 103 | universal_newlines=True, |
| 104 | ) |
| 105 | stdout, stderr = proc.communicate() |