私はコンテキストマネージャーであるmmap
を使用するコンテキストマネージャを作成しようとしています。当初私はオープンファイルの問題を抱えていました[なぜPermissionError:[WinError 32]を取得していないのですか?] hereと答えがすぐにと答えた理由はです。なぜコンテキストマネージャはファイルディスクリプタを閉じていませんか?
この情報があれば、私は問題を修正する2つの方法を試みましたが、どちらも問題なく動作しています。
最初のアプローチは、contextlib
の@contextmanager
デコレータを使用することでした:
from contextlib import contextmanager
import os
import mmap
#contextmanager
def memory_map(filename, access=mmap.ACCESS_WRITE):
size = os.path.getsize(filename)
fd = os.open(filename, os.O_RDWR)
print('about to yield')
with mmap.mmap(fd, size, access=access) as m:
yield m
print('in finally clause')
os.close(fd) # Close the associated file descriptor.
test_filename = 'data'
# First create the test file.
size = 1000000
with open(test_filename, 'wb') as f:
f.seek(size - 1)
f.write(b'\x00')
# Read and modify mmapped file in-place.
with memory_map(test_filename) as m: # Causes AttributeError: __enter__
print(len(m))
print(m[0:10])
# Reassign a slice.
m[0:11] = b'Hello World'
# Verify that changes were made
print('reading back')
with open(test_filename, 'rb') as f:
print(f.read(11))
# Delete test file.
# Causes:
# PermissionError: [WinError 32] The process cannot access the file because it
# is being used by another process: 'data'
os.remove(test_filename)
をしかし、それは、その結果:
:私は明示的コンテキストマネージャクラスを作成しようとした次の試行ではTraceback (most recent call last):
File "memory_map.py", line 27, in <module>
with memory_map(test_filename) as m: # Causes AttributeError: __enter__
AttributeError: __enter__
import os
import mmap
class MemoryMap:
def __init__(self, filename, access=mmap.ACCESS_WRITE):
print('in MemoryMap.__init__')
size = os.path.getsize(filename)
self.fd = os.open(filename, os.O_RDWR)
self.mmap = mmap.mmap(self.fd, size, access=access)
def __enter__(self):
print('in MemoryMap.__enter__')
return self.mmap
def __exit__(self, exc_type, exc_value, traceback):
print('in MemoryMap.__exit__')
os.close(self.fd) # Close the associated file descriptor.
print(' file descriptor closed')
test_filename = 'data'
# First create the test file.
size = 1000000
with open(test_filename, 'wb') as f:
f.seek(size - 1)
f.write(b'\x00')
# Read and modify mmapped file in-place.
with MemoryMap(test_filename) as m:
print(len(m))
print(m[0:10])
# Reassign a slice.
m[0:11] = b'Hello World'
# Verify that changes were made
print('reading back')
with open(test_filename, 'rb') as f:
print(f.read(11))
# Delete test file.
# Causes PermissionError: [WinError 32] The process cannot access the file
# because it is being used by another process: 'data'
os.remove(test_filename)
これはさらにそれを行うが、PermissionError
は、バックこれはあなたが作成された出力で見ることができるようにファイルディスクリプタはそのバージョンで閉じだったので、本当に私を混乱させる:だから、私は再びこだわっているようだ
in MemoryMap.__init__
in MemoryMap.__enter__
1000000
b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
in MemoryMap.__exit__
file descriptor closed
reading back
b'Hello World'
Traceback (most recent call last):
File "memory_map2.py", line 47, in <module>
os.remove(test_filename)
PermissionError: [WinError 32] The process cannot access the file because it is being used by another process: 'data'
。何が間違っているか(そしてそれを修正する方法)のアイデア?また、彼らは両方の問題を解決することができます、あなたは意見がある場合はどちらが良いですか?
ソリューション
両方のスニペット中にエラーが発生しました。これは最初の簡単な誤植でした。 contextmanger
デコレータはコメントアウトされました。されている必要があります:それはだった二で
@contextmanager # Leading "#" changed to "@".
def memory_map(filename, access=mmap.ACCESS_WRITE):
size = os.path.getsize(filename)
fd = os.open(filename, os.O_RDWR)
,,,
mmap
自体が__exit__()
方法、ちょうど関連したファイルディスクリプタに閉鎖されていなかったため。それは私には起こりませんでした。なぜなら、発生した例外は最初のケースと同じだったからです。 2番目の試みの場合
def __exit__(self, exc_type, exc_value, traceback):
print('in MemoryMap.__exit__')
self.mmap.close() # ADDED.
os.close(self.fd) # Close the associated file descriptor.
print(' file descriptor closed')
を?私はそのエラーだけを読んだ。 https://stackoverflow.com/questions/27215462/file-handling-in-python-permissionerror-werror-32-the-process-cannot-acce –
'#contextmanager'は' @ contextmanager'ではありません。 – user2357112
また、 "in finally clause"は実際には 'finally'節にはありません。 – user2357112