13

Windowsでマルチプロセッシングを使用すると、開いているファイルハンドルはすべて生成されたプロセスに継承されているように見えます。これには、それらをロックするという不快な副作用があります。

私は次のいずれかに興味があります:
1)継承の防止
2)生成されたプロセスからファイルを解放する方法

OSXでは正常に動作するが、os.renameのWindowsではクラッシュする次のコードについて考えてみます。

from multiprocessing import Process
import os

kFileA = "a.txt"
kFileB = "b.txt"

def emptyProcess():
    while 1:
        pass

def main():
    # Open a file and write a message
    testFile = open(kFileA, 'a')
    testFile.write("Message One\n")

    # Spawn a process
    p = Process(target=emptyProcess)
    p.start()

    # Close the file
    testFile.close()

    # This will crash
    # WindowsError: [Error 32] The process cannot access the file
    #               because it is being used by another process
    os.rename(kFileA, kFileB)

    testFile = open(kFileA, 'a')
    testFile.write("Message Two\n")
    testFile.close()

    p.terminate()


if __name__ == "__main__":
    main()
4

4 に答える 4

5

このfileno()メソッドは、ランタイム ライブラリによって割り当てられたファイル番号を返します。ファイル番号を指定すると、呼び出しmsvcrt.get_osfhandle()て Win32 ファイル ハンドルを取得できます。への呼び出しでこのハンドルを使用しSetHandleInformationます。したがって、次のようなものが機能する可能性があります。

win32api.SetHandleInformation(
    msvcrt.get_osfhandle(testFile.fileno()),
    win32api.HANDLE_FLAG_INHERIT,
    0)

このモジュールの正確な使用方法については確信が持てませんwin32apiが、これは Python ファイル オブジェクトと Win32 ハンドルの間のギャップを埋めるのに役立つはずです。

于 2009-06-11T23:05:35.887 に答える
3

multiprocessingモジュールについてはわかりませんが、 subprocessモジュールを使用すると、ファイル記述子を継承しないように指示できます。

close_fds が true の場合、子プロセスが実行される前に、0、1、および 2 を除くすべてのファイル記述子が閉じられます。(Unix のみ)。または、Windows では、close_fds が true の場合、ハンドルは子プロセスによって継承されません。Windows では、close_fds を true に設定したり、stdin、stdout、または stderr を設定して標準ハンドルをリダイレクトしたりすることはできないことに注意してください。

または、子プロセスのすべてのファイル記述子をos.closerangeで閉じることもできます

エラーを無視して、fd_low (包括的) から fd_high (排他的) までのすべてのファイル記述子を閉じます。可用性: Unix、Windows。

于 2009-06-04T01:41:10.920 に答える
0

ファイルハンドルを開いた後、SetHandleInformation()関数を使用してHANDLE_FLAG_INHERITフラグを削除できます。

于 2009-06-04T01:20:52.380 に答える
0

ローテーション ログとマルチプロセッシングを使用しているときに、この問題が発生しました。親プロセスがログをローテーションしようとすると、エラーで失敗します。

WindowsError: [エラー 32] 別のプロセスで使用されているため、プロセスはファイルにアクセスできません

他のいくつかの回答に基づいて、ログファイルハンドラーが継承されないようにするためのPython 2.7での実用的なソリューションを以下に示します

fd = logging.getLogger().handlers[0].stream.fileno() # The log handler file descriptor
fh = msvcrt.get_osfhandle(fd) # The actual windows handler
win32api.SetHandleInformation(fh, win32con.HANDLE_FLAG_INHERIT, 0) # Disable inheritance

この問題は Python 3.4 でいくらか対処されていることに注意してください。詳細については、 https: //www.python.org/dev/peps/pep-0446/ を参照してください。

于 2016-03-30T09:04:36.297 に答える