我正在通過Python執行外部程序。我想知道調用外部程序的最佳選擇,subprocess.Popen()
或subprocess.call()
。另外,我需要測量經過時間,外部程序使用的內存和CPU的數量。我聽說過psutil
,但我真的不知道該選哪個。測量已用時間,extern程序使用的內存和CPU的數量
回答
我也需要測量經過時間,由EXTERN程序
(我會假設你只需要在你的平臺的rusage
,而且提供的信息使用的內存和CPU的數量,因爲Windows根本就沒有這種東西,所以我也假設你不關心Windows如果你需要額外的信息,只能用某種特定於平臺的方式(讀取Linux的proc
文件系統,或者調用AIX的顯示器API或其他),你幾乎不能用stdlib來做這件事,而psutil
的答案是唯一的答案。)
subprocess
庫包裝調用fork
,然後execv
子項中的家庭功能和父項中的家庭功能waitpid
。 (您可以通過與源開始call
和追查下到從那裏的其他呼叫看到這一點。)
不幸的是,簡單的方法來從一個孩子得到的資源使用情況是調用wait3
或wait4
,不wait
或waitpid
。所以subprocess
讓你瘋狂接近你想要的,但不是那裏。
但是,你有幾個選擇:
- 如果你只有一個孩子的過程,
getrusage(RUSAGE_CHILDREN)
是你所需要的。 - 您可以啓動該過程,然後在收穫子女之前使用
psutil
(或平臺特定的代碼)從proc.pid
獲取資源信息。 - 您可以使用
psutil
來完成所有操作,並將subprocess
留下。 - 您可以繼承
subprocess.Popen
以覆蓋其wait
方法。
最後一個比聽起來簡單得多。如果你看到源代碼,實際上只有3個地方os.waitpid
被調用,並且只有其中一個會影響你的代碼;我認爲這是_try_wait
中的一個。所以(未經測試):
class ResourcePopen(subprocess.Popen):
def _try_wait(self, wait_flags):
"""All callers to this function MUST hold self._waitpid_lock."""
try:
(pid, sts, res) = _eintr_retry_call(os.wait4, self.pid, wait_flags)
except OSError as e:
if e.errno != errno.ECHILD:
raise
# This happens if SIGCLD is set to be ignored or waiting
# for child processes has otherwise been disabled for our
# process. This child is dead, we can't get the status.
pid = self.pid
sts = 0
else:
self.rusage = res
return (pid, sts)
def resource_call(*popenargs, timeout=None, **kwargs):
"""Run command with arguments. Wait for command to complete or
timeout, then return the returncode attribute and resource usage.
The arguments are the same as for the Popen constructor. Example:
retcode, rusage = call(["ls", "-l"])
"""
with ResourcePopen(*popenargs, **kwargs) as p:
try:
retcode = p.wait(timeout=timeout)
return retcode, p.rusage
except:
p.kill()
p.wait()
raise
現在:
retcode, rusage = resource_call(['spam', 'eggs'])
print('spam used {}s of system time'.format(rusage.ru_stime))
(在許多平臺上使用這種方式時甚至不會工作...),與此相比,使用帶有psutil
混合:
p = subprocess.Popen(['spam', 'eggs'])
ps = psutil.Process(p.pid)
p.wait()
print('spam used {}s of system time'.format(ps.cpu_times().system))
當然,後者不是更復雜的原因不是很好,它更復雜,因爲它更加強大和靈活;您還可以獲取rusage
不包含的各種數據,並且您可以在該過程正在運行時每秒獲取信息,而不必等待完成,並且可以在Windows上使用它,等等......
感謝您精心製作的答案!我正在使用psutil方法,但是當我嘗試運行我的file.py時,回溯導致:psutil.NoSuchProcess:進程不再存在。這是來自最後一次印刷。我能做什麼? – 2014-10-21 00:39:00
@ C.Porto:好的,一些'psutil'函數在獲得進程後不能使用,有些可以,列表取決於平臺。這就是爲什麼混合解決方案(使用'subprocess'來運行,使用'psutil'來衡量它們)是最糟糕的選擇......如果你不需要使用psutil 1.x和['psutil。 Popen'](http://pythonhosted.org//psutil/#popen-class)具有足夠的功能,請嘗試。我相信它給了你一個'psutil.Process'子類,並且保證能夠在'communic'和'wait'調用之間訪問它的東西,但是我可能是錯的。 – abarnert 2014-10-21 01:02:23
顯然,在這個過程獲得成功後,我真的不允許看到過程信息(我在Mac OS X上),即使使用psutil.Popen,你知道是否有其他方式來測量內存和CPU嗎?該過程得到收穫)? – 2014-10-21 02:16:39
- 1. 在Julia中測量已用CPU時間
- 2. 是否可以測量應用程序使用的「CPU時間」?
- 3. 使用java.lang.management測量Java控制檯應用程序使用的內存和CPU
- 4. 測量Ç執行時間,內存佔用和CPU負載爲一個程序
- 5. 測量程序的CPU/RAM使用率
- 6. 測量Maple函數的執行時間和CPU使用率
- 7. CPU時間測量
- 8. 用於測量CPU和內存使用情況的RRD
- 9. 測量進程CPU和內存使用情況
- 10. 如何測量一段程序的用戶/系統CPU時間?
- 11. 如何測量F#代碼的CPU和內存使用情況?
- 12. 如何通過python程序減少CPU和內存使用量?
- 13. 測量已用時間requestAnimFrame
- 14. 遠程測量已用時間
- 15. 測量CUDA程序和CUDA內核耗用時間的問題
- 16. 如何在負載測試期間測量CPU和內存
- 17. 如何測量Weblogic avg/max內存和cpu利用率在特定時間段?
- 18. Jprofiler - Jprofiler在錄製CPU時佔用大量CPU和內存
- 19. 關於使用CPU時鐘測量時間的問題
- 20. 在C++多線程程序中測量已用時間
- 21. 在構建期間如何測量CPU,內存和磁盤使用情況?
- 22. 測量CPU和子進程
- 23. 用QML測量已用時間
- 24. 使用clock()函數測量程序的運行時間
- 25. 如何測量java應用程序的使用內存?
- 26. 測量分佈式應用程序的內存使用情況
- 27. 測量ios應用程序的內存使用情況
- 28. 測量的Perl程序的峯值內存使用Valgrind的
- 29. 在JAVA中測量部分代碼的CPU使用時間
- 30. 測量JavaScript函數的內存使用情況,執行時間和性能
[ 'subprocess.call'](https://hg.python.org/cpython/file/4ea3cc4d1d9d/Lib/subprocess.py#l533)是'subprocess.Popen'的薄包裝。查看源代碼應該可以幫助您瞭解這些差異。 – mgilson 2014-10-20 22:01:56