只有循环中的第一个 subprocess.Popen(..., stdin=f) 才能正常工作

Only first subprocess.Popen(..., stdin=f) in a loop works correctly

我这里的主要目标是获取所有 cpu 连接计算机列表的 Linux 费用。我已经在网上挣扎和搜索了一段时间,但我一定错过了一些东西,因为我找不到答案。 所以我定义了一个 cpu_script.py :

import psutil

print(psutil.cpu_percent(interval=1,percpu=True))

在我的主脚本中调用,它在同一个文件夹中,与:

import subprocess
import os
import numpy as np
import psutil

usr = "AA"
computer = ["c1", "c2", "c3"] #list of computer which cpu load is to be tested
cpu_script = os.path.join(os.getcwd(),"cpu_script.py")

with open(cpu_script,"rb") as f:
    for c in computer:
        input(c)
        process = subprocess.Popen(["ssh","-X",usr + "@" + c,"python3","-u","-"], stdin=f, stdout=subprocess.PIPE)
        out = process.communicate()[0]
        input(out)

现在这是我从这些 input 中得到的:

>> c1 #first computer
>> <subprocess.Popen object at 0x7fd210aab358>
>> b'[1.0, 7.1, 0.0, 1.0, 2.0, 2.0, 3.0, 0.0, 0.0, 0.0, 0.0, 1.0]\n'
>> c2 #second computer
>> <subprocess.Popen object at 0x7fd210aab390>
>> b''
>> c3 #third computer
>> <subprocess.Popen object at 0x7fd210aab390>
>> b''

所以这是我的问题:为什么第二个和第三个输出是空的?我怎样才能得到它们?

我怀疑是我的第一个流程做的不好"closed",所以我尝试在input(out)之后加一个process.wait()或者一个process.kill(),但是没有有用

预先感谢您的帮助!


编辑:subprocess.check_output() 给出相同的输出。我还尝试了 subprocess.run 和:

with open(cpu_script,"rb") as f:
    for c in computer:
        input(c)
        process = subprocess.run(["ssh","-X",usr + "@" + c,"python3","-u","-"], stdin=f, stdout=subprocess.PIPE)
        input(out)

并得到:

>> c1 #first computer
>> CompletedProcess(args=['ssh', '-X', 'usr@c1', 'python3', '-u', '-'], returncode=0, stdout=b'[2.0, 1.0, 1.0, 2.9, 7.0, 0.0, 2.0, 1.0, 0.0, 0.0, 0.0, 1.0]\n')
>> c2 #second computer
>> CompletedProcess(args=['ssh', '-X', 'usr@c2', 'python3', '-u', '-'], returncode=0, stdout=b'')
>> c3 #third computer
>> CompletedProcess(args=['ssh', '-X', 'usr@c3', 'python3', '-u', '-'], returncode=0, stdout=b'')

这里的问题是,一旦你的文件被读取一次,指针就在文件的末尾,所以没有什么可以读取的了(所以你第二次为同一个文件传递 stdin=f , 剩下的只是空的)。

每次要使用文件时,反转内部循环和外部循环以重新打开文件一次:

for c in computer:
    with open(cpu_script, "rb") as f:
        process = subprocess.Popen(["ssh", "-X", "-l", usr, c, "python3 -u -"],
                                   stdin=f, stdout=subprocess.PIPE)
        out = process.communicate()[0]

...或使用 seek() 函数倒回到内部循环之间的开头:

with open(cpu_script, "rb") as f:
    for c in computer:
        f.seek(0)   ### <- THIS RIGHT HERE
        process = subprocess.Popen(["ssh", "-X", "-l", usr, c, "python3 -u -"],
                                   stdin=f, stdout=subprocess.PIPE)
        out = process.communicate()[0]