2013-05-29 3 views
5

구성 파일과 상호 작용하는 라이브러리가 있습니다. 라이브러리를 가져 오면 초기화 코드가 구성 파일을 읽고 가능하면 업데이트 한 다음 변경된 내용이없는 경우에도 파일에 업데이트 된 내용을 다시 씁니다.파이썬은 언제 파일을 디스크에 씁니까?

매우 가끔 구성 파일의 내용이 사라지는 문제가 발생합니다. 특히 이것은 짧은 스크립트 (라이브러리를 사용하여)를 여러 번 호출하여 수천 번 연속 실행할 때 발생합니다. 그것은 동일한 디렉토리에서 결코 발생하지 않으며, 이것은 다소 임의적 인 문제, 특히 IO를 가진 경쟁 조건이라고 믿게합니다.

이 문제는 안정적으로 문제를 재현 할 수 없으며 일부 시스템에서만 발생하기 때문에 디버깅하는 데 어려움이 있습니다. 필자는 무슨 일이 일어날 지 의심 스럽지만 파이썬에서 파일 I/O에 대한 내 그림이 올바른지 알고 싶다.

질문 : 파이썬 프로그램이 실제로 파일 내용을 디스크에 기록하는시기는 언제입니까? 파일이 닫힌 시간까지 내용이 디스크에 저장 될 것이라고 생각했지만이 오류를 설명 할 수는 없습니다. 파이썬이 파일을 닫을 때, 내용을 디스크 자체로 플러시하거나 파일 시스템에 큐에 넣을 수 있습니까? 파이썬이 종료 된 후 파일 내용을 디스크에 쓸 수 있습니까?fp.flush(); os.fsync(fp.fileno()) (fp은 파일 핸들)을 사용하여이 문제를 방지 할 수 있습니까?

문제가 생기면 유닉스 시스템 (특히 Mac OS X)에서 프로그래밍하고 있습니다. 편집 : 또한 프로세스가 동시에 실행되고 있지 않습니다.

부록 :

  1. 이 프로세스 # 1

    를 호출 : 여기에 내가 생각하는 특정 경쟁 조건입니다.
  2. 프로세스 # 1은 구성 파일을 읽기 모드로 열고 완료되면 닫습니다.
  3. 프로세스 # 1은 구성 파일을 쓰기 모드로 열고 모든 내용을 지 웁니다. 내용 지우기가 디스크에 동기화됩니다.
  4. 프로세스 # 1은 새 내용을 파일 핸들에 쓰고 닫습니다.
  5. 프로세스 # 1 : 파일을 닫으면 Python이 OS에이 내용을 디스크에 대기열에 기록하도록 지시합니다.
  6. 프로세스 # 1 닫히고
  7. 프로세스 # 2를 종료는
  8. 프로세스 # 2 읽기 모드로 구성 파일을 엽니 다 호출하지만, 새로운 내용이 아직 동기화되지 않습니다. 프로세스 # 2는 빈 파일을 봅니다.
  9. 프로세스 2가 파일을 읽은 후 OS가 마침내 디스크에 내용 쓰기를 완료했습니다.
  10. 프로세스 2는 파일이 비어 있다고 생각하고 구성 파일의 기본값을 설정합니다.
  11. 프로세스 # 2는 구성 파일의 버전을 디스크에 쓰고 마지막 버전을 덮어 씁니다.
+5

아니요, 아니요, 파이썬이 파일을 닫으면 파일이 디스크로 플러시되었습니다. 나는 당신이 생각하는 것보다 프로세스 # 2가 파일을 일찍 열 것이라고 말하고 싶다. –

+2

여러 프로세스가 동시에 파일에 액세스하고 이들 중 하나 이상이 파일에 쓰는 경우 일관된 결과를 얻기 위해 프로세스를 동기화해야합니다. 파이썬에만 국한된 것은 아닙니다. –

+2

OS가 데이터를 디스크에 쓰지 않더라도 파일에 액세스하는 모든 사람이 공유하는 메모리 캐시가 있기 때문에 파이썬에서 플러시되는 한 파일의 내용을 2. 프로세스로 반환합니다. . (일관성을 위해 구성되지 않은 공유 파일 시스템의 다른 컴퓨터에서 프로세스를 실행하거나 파일을 덮어 쓰는 경쟁 조건이없는 경우) – nos

답변

1

거의 확실하게 파이썬의 잘못이 아닙니다. 파이썬이 파일을 닫으면 OR이 신호로 종료되지 않고 정상적으로 종료되면 OS는 파일의 새로운 내용을 갖게됩니다. 이후에 열리면 새 내용이 반환됩니다. 더 복잡한 일이 있어야합니다. 다음은 몇 가지 생각입니다.

  1. 당신이 말하는 것은 파이썬 버그보다 파일 시스템 버그 일 가능성이 높고 파일 시스템 버그는 거의 없습니다.

  2. 파일 시스템이 실제로 원격 파일 시스템에있는 경우 파일 시스템 버그가 발생할 가능성이 훨씬 높습니다. 그들은 할?

  3. 모든 프로세스가 동일한 파일을 사용합니까? 파일에서 "ls -li"를 수행하여 inode 번호를 확인하고 변경 여부를 확인하십시오. 시나리오에서는 그렇게해서는 안됩니다. 뭔가가 파일을 이동하거나 디렉터리를 이동하거나 디렉터리를 삭제하고 다시 만들 가능성이 있습니까? 심볼릭 링크가 포함되어 있습니까?

  4. 프로그램 실행에 중복이 없습니까? 그 중 어떤 것이 끝나면 (즉, 백그라운드에서) "&"의 쉘에서 실행됩니까? 그것은 쉽게 첫 번째 것이 끝나기 전에 두 번째 것이 시작된다는 것을 의미 할 수 있습니다.

  5. 동일한 파일에 다른 프로그램을 쓰고 있습니까?

  6. 이것은 질문이 아니지만 원자 적 변경이 필요한 경우 (병렬로 실행되는 모든 프로그램이 이전 버전 또는 새 버전 만 볼 수 있도록 빈 파일이 아님), 달성 방법은 다음과 같습니다. 새 내용을 다른 파일 (예 : "foo.tmp")에 기록한 다음 os.rename ("foo.tmp", "foo")을 수행하십시오. 이름 바꾸기는 원자 적입니다.

+0

이것은 내가 바라는 최선의 대답이다. 고맙습니다! – HardlyKnowEm

+0

인턴이 라이브러리 함수를 편집하여 (동일한 모듈을 사용하여) 또 다른 파이썬 하위 프로세스를 생성했습니다. 그 변화를 되 돌린 후에, 그 문제는 사라진 것처럼 보였다. 그것은 아마도 인턴의 컴퓨터에서만 문제가 발생한 이유를 설명하기도합니다. – HardlyKnowEm

+0

다행스럽게 생각해 냈습니다! –

관련 문제