Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/358.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/tfs/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
python(Windows)中的多个shell命令_Python_Windows_Python 3.x_Subprocess_Popen - Fatal编程技术网

python(Windows)中的多个shell命令

python(Windows)中的多个shell命令,python,windows,python-3.x,subprocess,popen,Python,Windows,Python 3.x,Subprocess,Popen,我正在windows计算机上工作,我想在shell中设置一个变量,并想将其与另一个shell命令一起使用,如: set variable = abc echo %variable% 我知道我可以使用os.system(com1和com2)来实现这一点,但我也知道,这被认为是“糟糕的风格”,应该可以通过使用子流程模块来实现,但我不知道如何实现。 以下是我到目前为止得到的信息: proc = Popen('set variable=abc', shell=True, stdin=PIPE, std

我正在windows计算机上工作,我想在shell中设置一个变量,并想将其与另一个shell命令一起使用,如:

set variable = abc
echo %variable%
我知道我可以使用os.system(com1和com2)来实现这一点,但我也知道,这被认为是“糟糕的风格”,应该可以通过使用子流程模块来实现,但我不知道如何实现。 以下是我到目前为止得到的信息:

proc = Popen('set variable=abc', shell=True, stdin=PIPE, stdout=PIPE, stderr=STDOUT)
proc.communicate(input=b'echo %variable%)

但这两行似乎都不起作用,两个命令都无法执行。此外,如果我键入不存在的命令,我不会得到错误。如何正确执行此操作?

Popen
只能执行一个命令或shell脚本。您可以使用
简单地将整个shell脚本作为单个参数提供
要分离不同的命令,请执行以下操作:

proc = Popen('set variable=abc;echo %variable%', shell=True)
>>> proc = Popen(['sh'], stdin=PIPE, stdout=PIPE, stderr=PIPE)
>>> proc.communicate('echo 1; echo 2\n')
('1\n2\n', '')
或者您实际上可以使用多行字符串:

>>> from subprocess import call
>>> call('''echo 1
... echo 2
... ''', shell=True)
1
2
0
最后一个
0
是流程的返回代码

communicate
方法用于写入进程的stdin。在您的情况下,该过程在运行
set variable
后立即结束,因此对
communicate
的调用实际上没有任何作用

您可以生成一个shell,然后使用
communicate
编写命令:

proc = Popen('set variable=abc;echo %variable%', shell=True)
>>> proc = Popen(['sh'], stdin=PIPE, stdout=PIPE, stderr=PIPE)
>>> proc.communicate('echo 1; echo 2\n')
('1\n2\n', '')
请注意,
communicate
完成后也会关闭流,因此不能多次调用。如果您想要交互式会话,您可以直接写入
proc.stdin
并从
proc.stdout
读取


顺便说一句:您可以将
env
参数指定为
Popen
,因此,根据具体情况,您可能需要改为:

proc = Popen(['echo', '%variable%'], env={'variable': 'abc'})

显然,这将使用
echo
可执行文件,而不是shell内置文件,但它避免使用
shell=True

Popen
启动的shell不会等待其标准输入;
set
命令运行,然后shell退出,而不尝试从标准输入中读取任何内容。在本例中,您的命令(从Python脚本的角度来看)是一个单shell脚本,碰巧由两个shell命令组成,而不是一对shell命令。我强烈建议在标题和标记中更明确地说明Windows。在UNIX上,你会得到一个完全不同的答案……不过,一般来说,你所依赖的东西(设置和扩展的shell变量)依赖于拥有一个shell,所以在UNIX世界中,最佳实践是完全重写你正在做的事情,使其完全不依赖于shell变量。这不起作用(对我来说)。如果我键入:proc=Popen('echo abc;echo 123',shell=True)output=proc.communicate()[0]打印(输出),我得到
abc;echo123
,因此它不会将其读取为两行/commands@AracKnight
>>从子流程导入调用>>>调用('echo 1;echo 2',shell=True)1 2
它对我有效。您应该确切地指定您在问题中使用的代码。另外,您是在Windows还是linux上?
在linux上工作,我不确定powershell/批处理文件是否使用不同的分隔符。但是:您也可以使用多行字符串作为命令
调用('echo 1\necho 2',shell=True)
。我在Windows 10 64位上工作。我在第一行将数据库连接的密码设置为环境变量,以便在下一行调用psql并连接到数据库。使用
call('echo abc\necho 123',shell=True)
我得到
abc
作为输出,所以第二个命令仍然不起作用。@AracKnight如果这是您的用例,我相信您应该按照我最后描述的做:通过
env
参数提供env变量,而不是使用shell进行黑客攻击。当我为Popen指定
env
参数时,如果不知道变量的确切路径,我就不能再调用psql了
psql.exe
,因为我通常从PATH变量运行它,如果它传递了一个
env
,它就会被Popen忽略。此外,尽管我可能能够解决我目前的问题,但我真的很想知道这些目标通常是如何实现的,因为我将来可能会遇到类似的问题。