我已经为此工作了几个小时,并且无法找到一个好的解决方案。有一点背景,我正在运行一个密码破解程序,该程序是从命令行关闭的源代码,但是当我的gpu温度过高时必须不断地暂停它。
我在这个程序中使用python进行其他操作,这是我喜欢的语言。无论如何,密码程序会定期更新它的执行情况,gpu温度等,并允许我随时暂停。
我的温度很好,但由于阻塞问题,我猜测我无法发送暂停命令。它至少没有做任何事情。我已经看过几个线程输出的例子,但是没有看到使用线程输入和输出而没有引起任何问题的东西。
我的意思是,据我所知,在目前的POPEN限制下,这可能是不可能的,但我会欣赏一些方向。
popen = Popen(command, stdout=PIPE, stdin=PIPE, shell=True)
lines_iterator = iter(popen.stdout.readline, b"")
while 1:
for line in lines_iterator:
cleanLine = line.replace("\n", "")
p = re.compile('[0-9][0-9]c Temp')
m = p.search(cleanLine)
print cleanLine
if m:
temperature = m.group(0)
if int(temperature[:2]) > 80:
overheating = True
print "overheating"
if overheating:
if "[s]tatus [p]ause [r]esume [b]ypass [q]uit" in line:
#It's not doing anything right here, it just continues
print popen.communicate("p")[0]
这是我的代码的要点。它还处于hacky阶段,所以我知道它可能没有遵循最佳编码实践。
答案 0 :(得分:1)
overheating
范围的初步答案感到困惑。我删除了答案的第一部分,因为它不再相关了。
communicate
将等待进程退出,因此在这种情况下可能不是您正在寻找的内容。如果你想让这个过程继续下去
你可以使用像popen.stdin.write("p")
这样的东西。您可能还需要发送" \ n"如果您的流程需要这样做的话。
此外,如果您对额外的依赖关系感到满意,您可能会对旨在控制交互式流程的pexpect
模块感兴趣。
答案 1 :(得分:1)
简单的便携式解决方案是use threads here。如果没有block buffering issues就足够了。
如果检测到过热(未测试),则读取输出并停止输入:
#!/usr/bin/env python
from subprocess import Popen, PIPE, CalledProcessError
from threading import Event, Thread
def detect_overheating(pipe, overheating):
with pipe: # read output here
for line in iter(pipe.readline, ''):
if detected_overheating(line.rstrip('\n')):
overheating.set() # overheating
elif paused: #XXX global
overheating.clear() # no longer overheating
process = Popen(args, stdout=PIPE, stdin=PIPE, bufsize=1,
universal_newlines=True) # enable text mode
overheating = Event()
t = Thread(target=detect_overheating, args=[process.stdout, overheating])
t.daemon = True # close pipe if the process dies
t.start()
paused = False
with process.stdin: # write input here
while process.poll() is None:
if overheating.wait(1): # Python 2.7+
# overheating
if not paused:
process.stdin.write('p\n') # pause
process.stdin.flush()
paused = True
elif paused: # no longer overheating
pass #XXX unpause here
paused = False
if process.wait() != 0: # non-zero exit status may indicate failure
raise CalledProcessError(process.returncode, args)