2014-12-23 6 views
2

나는 상대적으로 간단한 응용 프로그램을 구축하고 있는데, 디렉토리를 요청하고, 올바른지 확인한 다음, 그 중 하나를 제거하고 다른 내용으로 다시 작성합니다. 이 괴괴 망측 한 행동이 발생했습니다. 설명해 드리겠습니다.누구나 shutil.rmtree 및 shutil.copytree의 이상한 동작을 설명 할 수 있습니까?

대상 폴더 창이 열려 있고 비어 있고 액세스가 거부 된 경우 폴더에서 퇴장했습니다. 제거됩니다. 하지만 비어 있지 않은 경우, 예외가 발생하지 않고 대상 디렉토리 (비어있는 것)가 비게되고 원본 디렉토리의 파일로 채워집니다. 어떤 대상이든 관계없이 대상 폴더를 제거한 다음 원본 대상과 동일한 이름과 내용으로 다시 만들어야하기 때문에 이상합니다.

이것은 비어있을 때 비어 있지 않을 때 디렉토리를 탐색 할 때와 완전히 똑같은 예외가 있어서는 안됩니까? 차이점은 무엇입니까, 그것은 여전히 ​​폴더를 삭제하기로되어 있습니다. 거기에 논리적 인 설명이 있습니까? 또한 예외가있는 경우 왜 어쨌든 디렉토리가 제거됩니까? 이 특정 부분에 대한

코드 (명심하시기 바랍니다 내가 초보자 해요 :))

def Delete(self, dest): 

    try: 
     shutil.rmtree(dest) 
     self.Paste(self.src, dest) 
    except (IOError, os.error) as e: 
     print e 

def Paste(self, src, dest): 

    try: 
     shutil.copytree(src, dest) 
    except (IOError, os.error) as e: 
     print e 
+1

'Delete()'또는'Paste() '에서 액세스 거부 예외가 발생합니까? 'try' 블록에 문장이 여러 개있을 때를 말하기는 어렵습니다. 질문 전체를 추가하는 것이 가장 좋습니다. 읽을 수 있도록 4 칸만큼 들여 씁니다. – martineau

답변

1

이는 Windows에서 예상되는 동작 매우 간단합니다.

내부적으로 shutil.rmtree은 MSDN (http://msdn.microsoft.com/en-us/library/windows/desktop/aa363915%28v=vs.85%29.aspx)에 문서화되어있는 windows API 함수 DeleteFile을 호출합니다.

이 기능은 (내게로 highlite) 다음과 같은 속성이 있습니다 :

DeleteFile을 기능 가까이에 삭제 파일을 표시합니다. 따라서 파일의 마지막 핸들이 닫힐 때까지 파일 삭제가 발생하지 않습니다. 파일을 여는 CreateFile에 대한 후속 호출이 ERROR_ACCESS_DENIED와 함께 실패합니다. (당신이 디렉토리 나 아직도 그 디렉토리에 대한 핸들이있을 수 있습니다 무엇을 볼 수 있기 때문에, 예를 들어 바이러스 스캐너, Windows 탐색기) 다른 프로세스는 여전히 열린 핸들이있는 경우

, 그것은 사라지지 않을 것입니다.

일반적으로 붙여 넣기 작업에서 예외를 catch하고 이상한 바이러스 검사 예외를 처리하기 위해 수십 밀리 초 동안 여러 번 다시 시도하십시오.

약간의 보너스 : windbg 또는 ProcessExplorer를 사용하여 파일에 열린 핸들을 누가 남겨두고 있는지 확인할 수 있습니다. 프로세스 탐색기에서 핸들 찾기를 사용하고 파일 이름을 검색하면됩니다.

+0

좋아요,하지만 그 이유는 디렉토리가 비어 있지 않을 때 아무런 문제가없는 이유를 설명하지 못하기 때문에 혼란 스럽습니다. 다시 한번 : 프로그램은 무엇이든 상관없이 디렉토리를 삭제해야합니다. Windows 탐색기에서 디렉토리를보고 있는데 비어있어 예외가 있지만 비어 있지 않은 경우 아무 문제가 없습니다. 폴더가 삭제되는 동안 파일을 붙여 넣을 수 있음을 볼 수 있습니다. – zephi

+0

음, 이것은 경쟁 조건입니다.디렉토리가 비어 있으면 가장 짧은 경우 (단지 하나의'DeleteFile')가 있습니다. 비어 있지 않으면 shutil 코드가 많은 파일과 디렉토리를 반복적으로 삭제하므로 탐색기가 핸들을 제거하는 데 더 많은 시간을 갖습니다 다음'CreateFile' 호출이 일어나기 전에. 실제로 어떤 일이 발생했는지 알고 싶다면 windbg를 사용하고 커널 레벨 디버깅을해야합니다. – schlenk