0

実行中の環境で問題を引き起こしている python スクリプトがあります。「データを読み取るために開いたファイルパイプを解放しない」と言われました。問題は最後の行にあると思います。正しい変更を確実に行いたいと思います。これは Python 2.7 環境で実行されています。ありがとうございます。

#!/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)

close を追加する必要があることはわかっていますが、他にメモリ リークがないことを確認したくありません。追加する必要がありますか

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私は提案でこれを書き直しましたが、まだshell = Trueが必要です以下を参照してください

#!/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)

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
4

1 に答える 1

2

subprocess.callサブプロセスを一度に 1 つずつ実行するには、@tdelaney が提案したように使用できます。

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

は必要ありませんshell=True。直接subprocess実行されます。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()
于 2013-06-12T15:40:08.730 に答える