-2

ディレクトリ内のファイルを検索し、コンピューターの実行中に無限に検索するPythonスクリプトがあります。コードは次のとおりです。

import fnmatch
import os
import shutil
import datetime
import time
import gc
# This is a python script that removes the "conflicted" copies of
# files that dropbox creates when one computer has the same copy of
# a file as another computer. 
# Written by Alexander Alvonellos
# 05/10/2012

class cleanUpConflicts:
    rootPath = 'D:\Dropbox'
    destDir = 'D:\Conflicted'
    def __init__(self):
        self.removeConflicted()
        return

    def cerr(message):
        f = open('./LOG.txt', 'a')
        date = str(datetime.datetime.now())
        s = ''
        s += date[0:19] #strip floating point
        s += ' : '
        s += str(message)
        s += '\n'
        f.write(s)
        f.close()
        del f
        del s
        del date
        return

    def removeConflicted(self):
        matches = []
        for root, dirnames, filenames in os.walk(self.rootPath):
            for filename in fnmatch.filter(filenames, '*conflicted*.*'):
                matches.append(os.path.join(root, filename))
                cerr(os.path.join(root, filename))
                shutil.move(os.path.join(root, filename), os.path.join(destDir, filename))
        del matches
            return

def main():
    while True:
        conf = cleanUpConflicts()
        gc.collect()
        del conf
        reload(os)
        reload(fnmatch)
        reload(shutil)
        time.sleep(10)
    return

main()

ともかく。10秒ごとに約1メガを追加するメモリリークがあります。なぜメモリの割り当てが解除されないのかわかりません。それが終わるまでに、このスクリプトは試行することなく、メモリのギグを継続的に消費します。これはイライラします。誰かヒントはありますか?私はすべてを試したと思います。

ここで提案された変更のいくつかを行った後の更新されたバージョンは次のとおりです。

import fnmatch
import os
import shutil
import datetime
import time
import gc
import re
# This is a python script that removes the "conflicted" copies of 
# files that dropbox creates when one computer has the same copy of
# a file as another computer. 
# Written by Alexander Alvonellos
# 05/10/2012

rootPath = 'D:\Dropbox'
destDir = 'D:\Conflicted'

def cerr(message):
    f = open('./LOG.txt', 'a')
    date = str(datetime.datetime.now())
    s = ''
    s += date[0:19] #strip floating point
    s += ' : '
    s += str(message)
    s += '\n'
    f.write(s)
    f.close()
    return


def removeConflicted():
    for root, dirnames, filenames in os.walk(rootPath):
        for filename in fnmatch.filter(filenames, '*conflicted*.*'):
            cerr(os.path.join(root, filename))
            shutil.move(os.path.join(root, filename), os.path.join(destDir, filename))
return


def main():
    #while True:
    for i in xrange(0,2):
        #time.sleep(1)
        removeConflicted()
        re.purge()
        gc.collect()
    return
main()

私はこの問題についていくつかの調査を行いましたが、fnmatchにバグがある可能性があります。これには、使用後にパージされない正規表現エンジンがあります。そのため、re.purge()を呼び出します。私はこれを数時間いじくり回しました。

私はまた、それをしていることを発見しました:

print gc.collect()

反復ごとに0を返します。

私に反対票を投じた人は誰でも明らかに間違っています。ここで本当に助けが必要です。私が話していたリンクは次のとおりです。なぜこのPythonループでメモリリークが発生するのですか?

4

2 に答える 2

0

コードは次のように短縮できます。

import fnmatch
import os
import shutil
import datetime
import time

ROOT_PATH = r'D:/Dropbox'
DEST_DIR = r'D:/Conflicted'

def cerr(message, log):
    date = str(datetime.datetime.now())
    msg = "%s : %s\n" % (date[0:19], message)
    log.write(msg)

def removeConflicted(log):
    for root, dirnames, filenames in os.walk(ROOT_PATH):
        for filename in fnmatch.filter(filenames, '*conflicted*.*'):
            # 1: comment out this line and check for leak
            cerr(os.path.join(root, filename), log)
            # 2: then comment out this line instead and check
            shutil.move(
                os.path.join(root, filename), 
                os.path.join(DEST_DIR, filename))


def main():
    with open('./LOG.txt', 'a') as log:
        while True:
            print "loop"
            removeConflicted(log)
            time.sleep(10)

if __name__ == "__main__":
    main()

処理するファイルがない場合にメモリリークが発生するかどうかを確認します。つまり、空のディレクトリをポイントし、移動中にリークが発生しているかどうかを判断します。モジュールをいじる
必要はありません。re.purge()gc

于 2012-05-10T22:44:00.320 に答える
0

推測では、何かが各メインイテレーションで作成されたインスタンスへの参照を保持します。

提案:

  1. クラスを削除して1〜2個の関数を作成します
  2. ドロップマッチ; 使わないの?
  3. Windows用のinotify(Linux)または同様のものを見てください。dirを監視し、必要な場合にのみ動作できます。連続スキャンなし
于 2012-05-10T21:58:55.223 に答える