2013-06-12 36 views
0

我有一個python腳本,它正在運行的環境中導致一些問題。我被告知它「不會釋放它打開的文件管道來讀取數據」。我相信問題在最後一行。我想確保我做出正確的更改。這是在Python 2.7環境中運行謝謝。Python和管道/調用

#!/usr/bin/env python 

import subprocess 
import urllib 
from xml.dom import minidom 

ZIPCODE = '06840' 
TEMP_TYPE = 'f' 
HVAC_ZONES = ['HVAC'] 
TSTAT = 5 


WEATHER_URL = 'http://xml.weather.yahoo.com/forecastrss?p=' + ZIPCODE +'&u=' + TEMP_TYPE 
WEATHER_NS = 'http://xml.weather.yahoo.com/ns/rss/1.0' 

dom = minidom.parse(urllib.urlopen(WEATHER_URL)) 
ycondition = dom.getElementsByTagNameNS(WEATHER_NS, 'condition')[0] 
CURRENT_OUTDOOR_TEMP = ycondition.getAttribute('temp') 

for zone in HVAC_ZONES: 
    i =0 
    while i < TSTAT: 
     i += 1 
     subprocess.Popen(['/Users/RPM/Applications/RacePointMedia/sclibridge','writestate', zone + '.HVAC_controller.ThermostatCurrentRemoteTemperature'+ '_' + str(i),CURRENT_OUTDOOR_TEMP + TEMP_TYPE.upper()], stdin=subprocess.PIPE) 

我知道我需要添加一個關閉但不想確保我沒有任何其他內存泄漏。我需要添加

subprocess.close 

這是使用subprocess.call的更好方法嗎?你需要釋放/關閉subprocess.call()?

#!/usr/bin/env python 

import subprocess 
import urllib 
from xml.dom import minidom 

ZIPCODE = '06457' 
TEMP_TYPE = 'f' # f - farhenheit c- celsius (case sensative) 
HVAC_ZONES = ['HVAC', 'HVAC2'] 
TSTAT = 64 


WEATHER_URL = 'http://xml.weather.yahoo.com/forecastrss?p=' + ZIPCODE +'&u=' + TEMP_TYPE 
WEATHER_NS = 'http://xml.weather.yahoo.com/ns/rss/1.0' 

dom = minidom.parse(urllib.urlopen(WEATHER_URL)) 
ycondition = dom.getElementsByTagNameNS(WEATHER_NS, 'condition')[0] 
CURRENT_OUTDOOR_TEMP = ycondition.getAttribute('temp') 
print(CURRENT_OUTDOOR_TEMP) 

for zone in HVAC_ZONES: 
    i =0 
    while i < TSTAT: 
     i += 1 
     command = ['/Users/RPM/Applications/RacePointMedia/sclibridge','writestate', zone + '.HVAC_controller.ThermostatCurrentRemoteTemperature'+ '_' + str(i),CURRENT_OUTDOOR_TEMP + TEMP_TYPE]  
     subprocess.call(str(command),shell=True) 

編輯

OK我有建議,但我還需要下面

#!/usr/bin/env python 

#define imports 

import sys 
import subprocess 
import os 
from subprocess import STDOUT 

DEVNULL = open(os.devnull, "r+b") 

#start global definitions 
command = ['/Users/RPM/Applications/RacePointMedia/sclibridge servicerequest "Wine Cellar" "" "" "1" "" "Pause"'] 
#start main program 
subprocess.call(command, close_fds=True, stdin=DEVNULL, stdout=DEVNULL, stderr=STDOUT,shell=True) 

殼=真看我已經嘗試過這種無殼=真改寫這一點,我得到以下錯誤,我主要關心的是內存泄漏。

File "./test.py", line 14, in <module> 
    subprocess.call(commamd,close_fds=True) 
    File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/subprocess.py", line 493, in call 
    File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/subprocess.py", line 679, in __init__ 
    File "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/subprocess.py", line 1228, in _execute_child 
+0

做你想並行運行所有子進程還是一次運行一個子進程?你需要提供一些來自子進程的輸入/讀取輸出嗎?你需要知道他們的退出狀態嗎? – jfs

+0

你的解決方案几乎可以...嘗試'subprocess.call(command)'。 str(command)創建一個列表的python字符串表示,它不會創建shell會識別的東西。 subprocess.call將運行該命令並等待它完成。該命令的任何輸出都將顯示在屏幕上。 – tdelaney

+0

謝謝你的幫助。我只需要一次運行一個。我不需要任何來自子進程的輸入/讀取輸出,我只需要按原樣運行該命令。我不需要知道退出狀態。 – ScottEdge

回答

2

要同時運行的子進程之一,你可以使用subprocess.call爲@tdelaney建議:

#.. 
call(command, close_fds=True, 
    stdin=DEVNULL, stdout=DEVNULL, stderr=STDOUT) 

你不需要shell=Truesubprocess將直接執行sclibridge

  • close_fds=True是爲了避免從父項繼承其他打開的文件描述符。
  • stdinstdoutstderr被設置爲提供空的輸入,並丟棄任何輸出

要同時並行運行nconcurrent子過程不脫離子過程泄漏文件描述符:

import os 
from subprocess import STDOUT, call 
from multiprocessing.dummy import Pool # use threads 

DEVNULL = open(os.devnull, "r+b") 
# define HVAC_ZONES, TSTAT, CURRENT_OUTDOOR_TEMP, TEMP_TYPE here 
#.. 
file_pattern = '.HVAC_controller.ThermostatCurrentRemoteTemperature'+ '_' 
def run(zone_i): 
    zone, i = zone_i 
    cmd = ['/Users/RPM/Applications/RacePointMedia/sclibridge', 
      'writestate', 
      zone + file_pattern + str(i), 
      CURRENT_OUTDOOR_TEMP + TEMP_TYPE] 
    return cmd, call(cmd, close_fds=True, 
        stdin=DEVNULL, stdout=DEVNULL, stderr=STDOUT) 

nconcurrent = 20 # limit number of concurrent processes 
commands = ((zone, i+1) for zone in HVAC_ZONES for i in range(TSTAT)) 
pool = Pool(nconcurrent) 
for cmd, returncode in pool.imap_unordered(run, commands): 
    if returncode != 0: 
     print("failed with returncode: %d, cmd: %s" % (returncode, cmd)) 
pool.close() 
pool.join() 
DEVNULL.close() 
+0

謝謝你的幫助。我會在今晚或明天嘗試。 – ScottEdge