为什么 subprocess.check_output 行会导致我的脚本崩溃?
Why is this subprocess.check_output line crashing my script?
我有一个脚本在 .pyw 中工作正常,但当转换为 .exe 时,(编辑:实际上,当我使用带有参数 -w
或 --windowed
的 pyinstaller 或--noconsole
它不起作用,但没有它们它会起作用)我发现这一行似乎使程序崩溃:
firstplan = subprocess.check_output(["powercfg", "-list"], shell=True ).split('\n')[3]
有人知道为什么吗?如果我将其注释掉,程序不会崩溃。我还有另外两条非常相似的线。
编辑:
也许把脚本放在这里是个好主意...
from __future__ import print_function
import os
# os.system('cls')
import psutil
import subprocess
loop = 1
while loop == (1):
CPUload = (psutil.cpu_percent(interval=4)) # CPU load
RAMload = (psutil.virtual_memory().percent) # RAM load
# os.system('cls')
print("CPU Load: ", end="") # Display CPU Load:
print(CPUload, "%") # Display CPUload
print("RAM Load: ", end="") # Display CPU Load:
print(str(RAMload) + " %") # Display RAMload
firstplan = subprocess.check_output(["powercfg", "-list"], shell=True ).split('\n')[3] # Selects a line
secondplan = subprocess.check_output(["powercfg", "-list"], shell=True ).split('\n')[4]
thirdplan = subprocess.check_output(["powercfg", "-list"], shell=True ).split('\n')[5]
firstplanID = ((firstplan.split(": "))[1].split(" (")[0]) # Extract XplanID from Xplan
secondplanID = ((secondplan.split(": "))[1].split(" (")[0])
thirdplanID = ((thirdplan.split(": "))[1].split(" (")[0])
activeplan = subprocess.check_output(["powercfg", "/getactivescheme"]) # Find the currently active plan
activeplanNAME = ((activeplan.split("("))[1].split(")")[0]) # Extract activeplanNAME from activeplan
firstplanNAME = ((firstplan.split("("))[1].split(")")[0]) # Extract XplanNAME from Xplan
secondplanNAME = ((secondplan.split("("))[1].split(")")[0])
thirdplanNAME = ((thirdplan.split("("))[1].split(")")[0])
if "High performance" in firstplanNAME: # Identify which plan is High performance
HighPerformance = firstplanNAME
HighPerformanceID = firstplanID
if "High performance" in secondplanNAME:
HighPerformance = secondplanNAME
HighPerformanceID = secondplanID
if "High performance" in thirdplanNAME:
HighPerformance = thirdplanNAME
HighPerformanceID = thirdplanID
if "Power saver" in firstplanNAME: # Identify which plan is Power saver
PowerSaver = firstplanNAME
PowerSaverID = firstplanID
if "Power saver" in secondplanNAME:
PowerSaver = secondplanNAME
PowerSaverID = secondplanID
if "Power saver" in thirdplanNAME:
PowerSaver = thirdplanNAME
PowerSaverID = thirdplanID
if activeplanNAME == PowerSaver: # Checks current plan name
print("Active plan: Power saver")
else:
if activeplanNAME == HighPerformance:
print("Active plan: High Performance")
else:
subprocess.check_output(["powercfg", "/s", HighPerformanceID])
if CPUload < 44:
if RAMload > 90:
if activeplanNAME == PowerSaver:
subprocess.check_output(["powercfg", "/s", HighPerformanceID])
print("Switching to High Performance by RAM load...")
if CPUload < 44:
if RAMload < 90:
if activeplanNAME == HighPerformance:
subprocess.check_output(["powercfg", "/s", PowerSaverID])
print("Switching to Power saver...")
if CPUload > 55:
if activeplanNAME == PowerSaver:
subprocess.check_output(["powercfg", "/s", HighPerformanceID])
print("Switching to High Performance...")
有问题的行是第21-23行。
有关更多信息,请向下滚动到评论和答案。
我不确定这是否能解决您的问题,但这里有一个重构解决了评论中指出的问题,以及您的代码的其他一些问题。
- 不要使用循环变量。 (反正没用过。)
- 不要 运行 相同的子进程三次。
- 避免不必要的
shell=True
- 为了一致性和可能的正确性,
/list
优于 -list
。
我已经删除了你的评论和我的内联评论,解释了到底发生了什么变化。
# Only necessary in Python 2, you really should be using Python 3 now
#from __future__ import print_function
# Only used in os.system('cls') which was commented out (for good reasons I presume)
#import os
import psutil
import subprocess
from time import sleep # see below
# Simply loop forever; break when done
while True:
# Remove gratuitous parentheses
CPUload = psutil.cpu_percent(interval=4)
RAMload = psutil.virtual_memory().percent
# Use .format() to inline a string
print("CPU Load: {}%".format(CPUload)))
print("RAM Load: {}%".format(RAMload))
# Only run subprocess once; use /list pro -list; don't use shell=True
pcfg = subprocess.check_output(["powercfg", "/list"], shell=False).split('\n')
# Additional refactoring below ########
firstplan = pcfg[3]
secondplan = pcfg[4]
thirdplan = pcfg[5]
# Get rid of wacky parentheses
firstplanID = firstplan.split(": ")[1].split(" (")[0]
secondplanID = secondplan.split(": ")[1].split(" (")[0]
thirdplanID = thirdplan.split(": ")[1].split(" (")[0]
activeplan = subprocess.check_output(["powercfg", "/getactivescheme"])
# Get rid of wacky parentheses
activeplanNAME = activeplan.split("(")[1].split(")")[0]
firstplanNAME = firstplan.split("(")[1].split(")")[0]
secondplanNAME = secondplan.split("(")[1].split(")")[0]
thirdplanNAME = thirdplan.split("(")[1].split(")")[0]
if "High performance" in firstplanNAME:
HighPerformance = firstplanNAME
HighPerformanceID = firstplanID
if "High performance" in secondplanNAME:
HighPerformance = secondplanNAME
HighPerformanceID = secondplanID
if "High performance" in thirdplanNAME:
HighPerformance = thirdplanNAME
HighPerformanceID = thirdplanID
if "Power saver" in firstplanNAME:
PowerSaver = firstplanNAME
PowerSaverID = firstplanID
if "Power saver" in secondplanNAME:
PowerSaver = secondplanNAME
PowerSaverID = secondplanID
if "Power saver" in thirdplanNAME:
PowerSaver = thirdplanNAME
PowerSaverID = thirdplanID
# Additional refactoring ends
if activeplanNAME == PowerSaver:
print("Active plan: Power saver")
# prefer if / elif / else over nested if
elif activeplanNAME == HighPerformance:
print("Active plan: High Performance")
else:
# What's this supposed to do? You are capturing, then discarding the output.
# Perhaps you are looking for subprocess.check_call()?
subprocess.check_output(["powercfg", "/s", HighPerformanceID])
if CPUload < 44:
# Combine conditions rather than nesting conditionals
if RAMload > 90 and activeplanNAME == PowerSaver:
# subprocess.check_call() here too?
subprocess.check_output(["powercfg", "/s", HighPerformanceID])
print("Switching to High Performance by RAM load...")
# Don't check if CPUload < 44: again
# Instead, just stay within this indented block
# Combine conditions
elif RAMload < 90 and activeplanNAME == HighPerformance:
# subprocess.check_call() here too?
subprocess.check_output(["powercfg", "/s", PowerSaverID])
print("Switching to Power saver...")
# What if RAMload == 90?
# Combine conditions
if CPUload > 55 and activeplanNAME == PowerSaver:
# subprocess.check_call() here too?
subprocess.check_output(["powercfg", "/s", HighPerformanceID])
print("Switching to High Performance...")
# Maybe sleep between iterations?
#sleep(1)
该脚本目前 运行 是一个相当紧凑的循环,您可能需要取消对最后一行的注释。
还有很多重复的代码。您可能需要考虑进一步重构以将三个计划收集到一个数组中,其中每个对象都是一个字典,其中的成员名称标识您提取的不同属性。
# Additional refactoring below ########
activeplan = subprocess.check_output(["powercfg", "/getactivescheme"])
activeplanNAME = activeplan.split("(")[1].split(")")[0]
plan = []
for idx in range(3):
raw = pcfg[3+idx]
thisplan = {'raw': raw}
thisplan['id'] = raw.split(": ")[1].split(" (")[0]
thisplan['name'] = raw.split("(")[1].split(")")[0]
if "High performance" in thisplan['name']:
HighPerformance = thisplan['name']
HighPerformanceID = thisplan['id']
if "Power saver" in thisplan['name']:
PowerSaver = thisplan['name']
PowerSaverID = thisplan['id']
plan[idx] = thisplan
现在您实际上可以更改 HighPerformance
和 PowerSaver
变量以仅记住 idx
然后如果需要,您可以从字典列表中提取名称plan[PowerSaverIdx]['name']
和 ID plan[PowerSaverIdx]['id']
.
我有一个脚本在 .pyw 中工作正常,但当转换为 .exe 时,(编辑:实际上,当我使用带有参数 -w
或 --windowed
的 pyinstaller 或--noconsole
它不起作用,但没有它们它会起作用)我发现这一行似乎使程序崩溃:
firstplan = subprocess.check_output(["powercfg", "-list"], shell=True ).split('\n')[3]
有人知道为什么吗?如果我将其注释掉,程序不会崩溃。我还有另外两条非常相似的线。
编辑:
也许把脚本放在这里是个好主意...
from __future__ import print_function
import os
# os.system('cls')
import psutil
import subprocess
loop = 1
while loop == (1):
CPUload = (psutil.cpu_percent(interval=4)) # CPU load
RAMload = (psutil.virtual_memory().percent) # RAM load
# os.system('cls')
print("CPU Load: ", end="") # Display CPU Load:
print(CPUload, "%") # Display CPUload
print("RAM Load: ", end="") # Display CPU Load:
print(str(RAMload) + " %") # Display RAMload
firstplan = subprocess.check_output(["powercfg", "-list"], shell=True ).split('\n')[3] # Selects a line
secondplan = subprocess.check_output(["powercfg", "-list"], shell=True ).split('\n')[4]
thirdplan = subprocess.check_output(["powercfg", "-list"], shell=True ).split('\n')[5]
firstplanID = ((firstplan.split(": "))[1].split(" (")[0]) # Extract XplanID from Xplan
secondplanID = ((secondplan.split(": "))[1].split(" (")[0])
thirdplanID = ((thirdplan.split(": "))[1].split(" (")[0])
activeplan = subprocess.check_output(["powercfg", "/getactivescheme"]) # Find the currently active plan
activeplanNAME = ((activeplan.split("("))[1].split(")")[0]) # Extract activeplanNAME from activeplan
firstplanNAME = ((firstplan.split("("))[1].split(")")[0]) # Extract XplanNAME from Xplan
secondplanNAME = ((secondplan.split("("))[1].split(")")[0])
thirdplanNAME = ((thirdplan.split("("))[1].split(")")[0])
if "High performance" in firstplanNAME: # Identify which plan is High performance
HighPerformance = firstplanNAME
HighPerformanceID = firstplanID
if "High performance" in secondplanNAME:
HighPerformance = secondplanNAME
HighPerformanceID = secondplanID
if "High performance" in thirdplanNAME:
HighPerformance = thirdplanNAME
HighPerformanceID = thirdplanID
if "Power saver" in firstplanNAME: # Identify which plan is Power saver
PowerSaver = firstplanNAME
PowerSaverID = firstplanID
if "Power saver" in secondplanNAME:
PowerSaver = secondplanNAME
PowerSaverID = secondplanID
if "Power saver" in thirdplanNAME:
PowerSaver = thirdplanNAME
PowerSaverID = thirdplanID
if activeplanNAME == PowerSaver: # Checks current plan name
print("Active plan: Power saver")
else:
if activeplanNAME == HighPerformance:
print("Active plan: High Performance")
else:
subprocess.check_output(["powercfg", "/s", HighPerformanceID])
if CPUload < 44:
if RAMload > 90:
if activeplanNAME == PowerSaver:
subprocess.check_output(["powercfg", "/s", HighPerformanceID])
print("Switching to High Performance by RAM load...")
if CPUload < 44:
if RAMload < 90:
if activeplanNAME == HighPerformance:
subprocess.check_output(["powercfg", "/s", PowerSaverID])
print("Switching to Power saver...")
if CPUload > 55:
if activeplanNAME == PowerSaver:
subprocess.check_output(["powercfg", "/s", HighPerformanceID])
print("Switching to High Performance...")
有问题的行是第21-23行。
有关更多信息,请向下滚动到评论和答案。
我不确定这是否能解决您的问题,但这里有一个重构解决了评论中指出的问题,以及您的代码的其他一些问题。
- 不要使用循环变量。 (反正没用过。)
- 不要 运行 相同的子进程三次。
- 避免不必要的
shell=True
- 为了一致性和可能的正确性,
/list
优于-list
。
我已经删除了你的评论和我的内联评论,解释了到底发生了什么变化。
# Only necessary in Python 2, you really should be using Python 3 now
#from __future__ import print_function
# Only used in os.system('cls') which was commented out (for good reasons I presume)
#import os
import psutil
import subprocess
from time import sleep # see below
# Simply loop forever; break when done
while True:
# Remove gratuitous parentheses
CPUload = psutil.cpu_percent(interval=4)
RAMload = psutil.virtual_memory().percent
# Use .format() to inline a string
print("CPU Load: {}%".format(CPUload)))
print("RAM Load: {}%".format(RAMload))
# Only run subprocess once; use /list pro -list; don't use shell=True
pcfg = subprocess.check_output(["powercfg", "/list"], shell=False).split('\n')
# Additional refactoring below ########
firstplan = pcfg[3]
secondplan = pcfg[4]
thirdplan = pcfg[5]
# Get rid of wacky parentheses
firstplanID = firstplan.split(": ")[1].split(" (")[0]
secondplanID = secondplan.split(": ")[1].split(" (")[0]
thirdplanID = thirdplan.split(": ")[1].split(" (")[0]
activeplan = subprocess.check_output(["powercfg", "/getactivescheme"])
# Get rid of wacky parentheses
activeplanNAME = activeplan.split("(")[1].split(")")[0]
firstplanNAME = firstplan.split("(")[1].split(")")[0]
secondplanNAME = secondplan.split("(")[1].split(")")[0]
thirdplanNAME = thirdplan.split("(")[1].split(")")[0]
if "High performance" in firstplanNAME:
HighPerformance = firstplanNAME
HighPerformanceID = firstplanID
if "High performance" in secondplanNAME:
HighPerformance = secondplanNAME
HighPerformanceID = secondplanID
if "High performance" in thirdplanNAME:
HighPerformance = thirdplanNAME
HighPerformanceID = thirdplanID
if "Power saver" in firstplanNAME:
PowerSaver = firstplanNAME
PowerSaverID = firstplanID
if "Power saver" in secondplanNAME:
PowerSaver = secondplanNAME
PowerSaverID = secondplanID
if "Power saver" in thirdplanNAME:
PowerSaver = thirdplanNAME
PowerSaverID = thirdplanID
# Additional refactoring ends
if activeplanNAME == PowerSaver:
print("Active plan: Power saver")
# prefer if / elif / else over nested if
elif activeplanNAME == HighPerformance:
print("Active plan: High Performance")
else:
# What's this supposed to do? You are capturing, then discarding the output.
# Perhaps you are looking for subprocess.check_call()?
subprocess.check_output(["powercfg", "/s", HighPerformanceID])
if CPUload < 44:
# Combine conditions rather than nesting conditionals
if RAMload > 90 and activeplanNAME == PowerSaver:
# subprocess.check_call() here too?
subprocess.check_output(["powercfg", "/s", HighPerformanceID])
print("Switching to High Performance by RAM load...")
# Don't check if CPUload < 44: again
# Instead, just stay within this indented block
# Combine conditions
elif RAMload < 90 and activeplanNAME == HighPerformance:
# subprocess.check_call() here too?
subprocess.check_output(["powercfg", "/s", PowerSaverID])
print("Switching to Power saver...")
# What if RAMload == 90?
# Combine conditions
if CPUload > 55 and activeplanNAME == PowerSaver:
# subprocess.check_call() here too?
subprocess.check_output(["powercfg", "/s", HighPerformanceID])
print("Switching to High Performance...")
# Maybe sleep between iterations?
#sleep(1)
该脚本目前 运行 是一个相当紧凑的循环,您可能需要取消对最后一行的注释。
还有很多重复的代码。您可能需要考虑进一步重构以将三个计划收集到一个数组中,其中每个对象都是一个字典,其中的成员名称标识您提取的不同属性。
# Additional refactoring below ########
activeplan = subprocess.check_output(["powercfg", "/getactivescheme"])
activeplanNAME = activeplan.split("(")[1].split(")")[0]
plan = []
for idx in range(3):
raw = pcfg[3+idx]
thisplan = {'raw': raw}
thisplan['id'] = raw.split(": ")[1].split(" (")[0]
thisplan['name'] = raw.split("(")[1].split(")")[0]
if "High performance" in thisplan['name']:
HighPerformance = thisplan['name']
HighPerformanceID = thisplan['id']
if "Power saver" in thisplan['name']:
PowerSaver = thisplan['name']
PowerSaverID = thisplan['id']
plan[idx] = thisplan
现在您实际上可以更改 HighPerformance
和 PowerSaver
变量以仅记住 idx
然后如果需要,您可以从字典列表中提取名称plan[PowerSaverIdx]['name']
和 ID plan[PowerSaverIdx]['id']
.