将列表传递给subprocess.run [英] Passing List to subprocess.run

查看:61
本文介绍了将列表传递给subprocess.run的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个包含列表的脚本-列表只是我想要传递给 subprocess.run 这样的一些args

  commands = ["bash命令1","bash命令2",..] 

这是我的代码

  commands = ["bash命令1","bash命令2",..]process = subprocess.run([命令],stdout = subprocess.PIPE,shell = True) 

如何将列表传递给subprocess.run?

这是回溯

  Traceback(最近一次通话最近):< module>中的文件"./retesting.py",第18行.process = subprocess.run([命令],stdout = subprocess.PIPE,shell = True)运行中的文件"/usr/lib/python3.5/subprocess.py",第383行使用Popen(* popenargs,** kwargs)作为进程:__init__中的文件"/usr/lib/python3.5/subprocess.py",行676restore_signals,start_new_session)_execute_child中的文件"/usr/lib/python3.5/subprocess.py",第1221行restore_signals,start_new_session,preexec_fn)TypeError:无法将列表"对象隐式转换为str 

我不知道自己在做什么错,我尝试了各种各样的事情,所以我非常感谢您的帮助

解决方案

在使用 shell = True 之前,您必须了解它的作用.使用 Popen 的文档.它指出:

shell 参数(默认为 False )指定是否使用shell作为要执行的程序.如果外壳为 True ,则为建议将args作为字符串而不是作为序列传递.

在带有 shell = True 的Unix上,shell默认为/bin/sh .如果 args 是一个字符串,该字符串指定要通过外壳执行的命令.这意味着该字符串必须完全按照其格式进行格式化在shell提示符下键入时.例如,这包括引号或反斜杠转义使用空格的文件名.如果 args 是一个顺序,第一项指定命令字符串,以及任何其他项目将被视为外壳程序的其他参数.也就是说, Popen 的作用等同于:

  Popen(['/bin/sh','-c',args [0],args [1],...]) 

在Windows上具有 shell = True COMSPEC 环境变量指定默认值壳.在Windows上唯一需要指定 shell = True 的时间是您希望执行的命令已内置到外壳程序中(例如 dir copy ).您不需要 shell = True 即可运行批处理文件或基于控制台的文件可执行文件.

无法一次性执行一系列命令,您要做的是在生成外壳程序作为该外壳程序的选项时,执行第一个命令以及所有其他通过的命令. ./p>

您要改为执行此操作:

 用于命令中的命令:subprocess.run(command,shell = True) 

或者:您希望将命令序列作为一个脚本执行:

  subprocess.run(';'.join(commands),shell = True) 

这就是说:如果命令中的命令只是可执行文件,则应避免使用 shell = True 并使用 shlex.split 提供已解析的参数列表.如果需要指定执行命令的目录,则可以对 Popen (或任何类似的函数)使用 cwd 参数.

在您的情况下,您需要以下内容:

  import os,subprocesssubprocess.run(['app','--email','some-email','--password','somepassword'],cwd = os.path.expanduser('〜/app-cli')) 

i've got a script, that contains a list - the list is just some args that I want to pass to subprocess.run like this

commands = ["bash command 1", "bash command 2",..]

here is my code

commands = ["bash command 1", "bash command 2",..]
process = subprocess.run([commands], stdout = subprocess.PIPE, shell = True)

how can I pass a list to my subprocess.run?

this is the Traceback

Traceback (most recent call last):
  File "./retesting.py", line 18, in <module>
    process = subprocess.run([commands], stdout = subprocess.PIPE, shell = True)
  File "/usr/lib/python3.5/subprocess.py", line 383, in run
    with Popen(*popenargs, **kwargs) as process:
  File "/usr/lib/python3.5/subprocess.py", line 676, in __init__
    restore_signals, start_new_session)
  File "/usr/lib/python3.5/subprocess.py", line 1221, in _execute_child
    restore_signals, start_new_session, preexec_fn)
TypeError: Can't convert 'list' object to str implicitly

I Have no idea what I'm doing wrong and I tried all sorts of things, so I'd appreciate really any help

解决方案

Before using shell=True you have to understand what it does. Take the documentation for Popen. It states:

The shell argument (which defaults to False) specifies whether to use the shell as the program to execute. If shell is True, it is recommended to pass args as a string rather than as a sequence.

On Unix with shell=True, the shell defaults to /bin/sh. If args is a string, the string specifies the command to execute through the shell. This means that the string must be formatted exactly as it would be when typed at the shell prompt. This includes, for example, quoting or backslash escaping filenames with spaces in them. If args is a sequence, the first item specifies the command string, and any additional items will be treated as additional arguments to the shell itself. That is to say, Popen does the equivalent of:

Popen(['/bin/sh', '-c', args[0], args[1], ...])

On Windows with shell=True, the COMSPEC environment variable specifies the default shell. The only time you need to specify shell=True on Windows is when the command you wish to execute is built into the shell (e.g. dir or copy). You do not need shell=True to run a batch file or console-based executable.

There is no way to execute a sequence of commands in one go, what you are doing is executing the first command and all other commands as passed when spawning the shell as options to that shell.

You want to do this instead:

for command in commands:
    subprocess.run(command, shell=True)

Alternatively: you want to execute the sequence of commands as a single script:

subprocess.run(';'.join(commands), shell=True)

This said: if the commands inside command are only executables you should really avoid using shell=True and use shlex.split to provide the parsed argument list. If you need to specify the directory where the command should be executed you can use the cwd argument to Popen (or any similar function).

In your case you want something like:

import os, subprocess

subprocess.run(['app', '--email', 'some-email', '--password', 'somepassword'], cwd=os.path.expanduser('~/app-cli'))

这篇关于将列表传递给subprocess.run的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆