2009-12-13 4 views
6

파이썬의 스레드와 tempfile 모듈에 흥미로운 문제가 있습니다. 스레드가 종료 될 때까지 뭔가 지워지지 않는 것처럼 보입니다. 열려있는 파일 제한에 대해 실행 중입니다. (이것은 OS X 10.5.8, Python 2.5.1입니다.)파이썬 임시 파일 모듈과 스레드가 훌륭하게 재생되지 않습니다. 내가 도대체 ​​뭘 잘못하고있는 겁니까?

그러나 tempfile 모듈이 수행하는 작업 (모든 보안 검사가 아니라 파일 설명자를 생성 한 후 OS를 사용)을 복제하면됩니다. fdopen을 사용하여 파일 객체 생성) 아무런 문제가 없습니다.

파이썬에 버그로 제출하기 전에 여기에서 확인해 보았습니다. 뭔가 잘못 처리 한 것 같아서요. 그러나 만약 내가 그렇다면, 그걸 알아 내려고 노력하는 날이 어디에도 없었습니다. 나는 worker_notempfile 라인 활성과 worker_tempfile 라인을 주석 처리로 실행하면

#!/usr/bin/python 

import threading 
import thread 
import tempfile 
import os 
import time 
import sys 

NUM_THREADS = 10000 

def worker_tempfile(): 
    tempfd, tempfn = tempfile.mkstemp() 
    tempobj = os.fdopen(tempfd, 'wb') 
    tempobj.write('hello, world') 
    tempobj.close() 
    os.remove(tempfn) 
    time.sleep(10) 

def worker_notempfile(index): 
    tempfn = str(index) + '.txt' 
    # The values I'm passing os.open may be different than tempfile.mkstemp 
    # uses, but it works this way as does using the open() function to create 
    # a file object directly. 
    tempfd = os.open(tempfn, 
        os.O_EXCL | os.O_CREAT | os.O_TRUNC | os.O_RDWR) 
    tempobj = os.fdopen(tempfd, 'wb') 
    tempobj.write('hello, world') 
    tempobj.close() 
    os.remove(tempfn) 
    time.sleep(10) 

def main(): 
    for count in range(NUM_THREADS): 
     if count % 100 == 0: 
      print('Opening thread %s' % count) 
     wthread = threading.Thread(target=worker_tempfile) 
     #wthread = threading.Thread(target=worker_notempfile, args=(count,)) 
     started = False 
     while not started: 
      try: 
       wthread.start() 
       started = True 
      except thread.error: 
       print('failed starting thread %s; sleeping' % count) 
       time.sleep(3) 

if __name__ == '__main__': 
    main() 

, 그것은 완료 될 때까지 실행됩니다.

다른 방법 주변 (worker_tempfile 사용) 나는 다음과 같은 오류가 발생합니다 : 내가 잘못

$ python threadtempfiletest.py 
Opening thread 0 
Opening thread 100 
Opening thread 200 
Opening thread 300 
Exception in thread Thread-301: 
Traceback (most recent call last): 
    File "/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/threading.py", line 460, in __bootstrap 
    File "/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/threading.py", line 440, in run 
    File "threadtempfiletest.py", line 17, in worker_tempfile 
    File "/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/tempfile.py", line 302, in mkstemp 
    File "/System/Library/Frameworks/Python.framework/Versions/2.5/lib/python2.5/tempfile.py", line 236, in _mkstemp_inner 
OSError: [Errno 24] Too many open files: '/var/folders/4L/4LtD6bCvEoipksvnAcJ2Ok+++Tk/-Tmp-/tmpJ6wjV0' 

어떤 아이디어 뭘하는지? 이것은 파이썬의 버그입니까, 아니면 제가 골치 썩은 것입니까?

업데이트 2009-12-14 : 나는 그 대답을 찾았지만 나는 그것을 좋아하지 않는다고 생각합니다. 아무도이 문제를 재현 할 수 없었기 때문에 나는 사무실을 돌아 다니며 기계를 사냥하러 갔다. 그것은 내 기계를 제외한 모든 것을 통과시켰다. 나는 내가 사용했던 것과 동일한 소프트웨어 버전으로 Mac에서 테스트했다. 나는 심지어 똑같은 하드웨어 및 소프트웨어 구성으로 데스크탑 G5를 사냥하러 갔다. 같은 결과였다. 두 테스트 모두 (임시 파일과 임시 파일 제외) 모든 것에 성공했습니다.

킥 들어, 내가 파이썬 2.6.4를 다운로드하고 내 데스크톱에서, 그리고 파이썬 2.5.1로 내 시스템에서 동일한 패턴을 시도 : tempfile이 실패하고 notempfile가 성공했습니다.

이것은 내 맥에서 무언가가 떠들썩하다는 결론을 이끌어 내고 있지만, 나는 무엇을 알아 내지 못했다. 어떤 제안이라도 환영합니다.

+1

좋은 코드는 명확한 질문으로 +1 할 수는 없습니다. –

+0

파이썬 버전을 제공해 줄 수 있습니까? 나는 그것이 중요한지는 모르지만 그것은 가능할 것이다. –

+0

Jonathan : 대단히 감사합니다! Peter : Python 2.5.1. 또한이를 반영하기 위해 질문을 편집했습니다. – Schof

답변

0

아무도이 문제를 재현 할 수 없었으므로 컴퓨터를 찾기 위해 사무실을 돌아 다니며갔습니다. 그것은 내 기계를 제외한 모든 것을 통과시켰다. 나는 내가 사용했던 것과 동일한 소프트웨어 버전으로 Mac에서 테스트했다. 나는 심지어 똑같은 하드웨어 및 소프트웨어 구성으로 데스크탑 G5를 사냥하러 갔다. 같은 결과였다. 두 테스트 모두 (임시 파일과 임시 파일 제외) 모든 것에 성공했습니다.

킥 들어, 내가 파이썬 2.6.4를 다운로드하고 내 데스크톱에서, 그리고 파이썬 2.5.1로 내 시스템에서 동일한 패턴을 시도 : tempfile이 실패하고 notempfile가 성공했습니다.

이것은 내 맥에서 무언가가 물결 친다는 결론을 이끌어 내고있다. 그래서 다른 누구도 영원히 도망 갈 수 없다.

감사합니다.이 문제에 많은 도움을 주신 모든 분들 (특히 Alex Martelli)에게 감사드립니다.

3

고객님의 답변은 here입니다. mkstemp이 제공하는 튜플의 첫 번째 부분으로 주어진 파일 설명자를 명시 적으로 os.close()해야합니다.

편집 : 아니요, OP는 이미 수행해야하는 작업을 수행하고 있습니다. 나는 좋은 링크에 대한 답변을 떠날거야.

+1

하지만 "os.fdopen (fd) 함수가 반환됩니다. 같은 파일 기술자를 사용하는 파이썬 파일 객체입니다.이 파일 객체를 닫으면 OS 레벨의 파일 기술자가 닫힙니다. "- 이것이 내 지식 중 가장 정확해야합니다. 그렇다면 왜 OP의 버그가 그렇게 신비 롭습니다 ... 그는 ** fdopen을 사용하고 파일 객체를 닫는 중입니다 ... 그럼에도 불구하고 그는 어쨌든 파일 설명자를 새고 있습니다. 이것은 심각한 미스테리입니다! –

+0

D' oh! 수정 해 주셔서 감사합니다.이 답변을 남겨 둘 것입니다. , 단지 링크 된 리소스가 유용하기 때문에. –

+0

나는이 게시물이 길다는 것을 알았지 만 유사한 문제에 대해 나를 퇴장시켰다 . 이것은 버그가있는 것처럼보기에 직관적이지 못하다. ''mkstemp ()''이 범위를 벗어나면 모든 것이 자체적으로 정리 될 것입니다 ... 그러나 일부 시스템에서는 그렇지 않습니다. 병렬 처리 루프가 끝날 때까지는 아닙니다. 다음 예는 컴퓨터가 디스크가 꽉 찼다 고 생각할 때 컴퓨터를 속이기위한 좋은 방법을 보여줍니다. 파일은 실제로 길을 따라 파괴되지만 OS는 프로그램이 종료 될 때까지 그것을 인식하지 못합니다. https : //gist.github.co.kr/ehhumphrey/b556c8be89fb6d5aeed1 –

4

Mac OS X 10.5.9에서 (Apple 자신의 빌드로) Python 2.5.1에서 문제를 재현 할 수 없습니다. 정상적으로 실행됩니다.

저는 Intel 프로세서 인 Macbook Pro와 PPC 프로세서 인 이전 PowerMac을 모두 사용해 보았습니다.

10.5.8에서 내가 눈치 채지 못한 버그가 있었을 것이라고 상상할 수 있습니다. 소프트웨어 업데이트가 제공 될 때마다 항상 업그레이드되므로 테스트 할 10.5.8이 없습니다. 내가 제안 할 수있는 것은 10.5.9로 업그레이드를 시도하고 버그가 사라지는 지 확인하는 것입니다. 그렇지 않으면 컴퓨터와 사용자의 동작 차이가 어떻게 될지 전혀 알 수 없습니다.

+0

흠. 10.5.8이 나에게 줄 소프트웨어 업데이트의 최신 버전 인 것으로 보입니다. 아마도 이것은 PowerPC 대 Intel의 것입니까? (나는 PowerPC에있다.) – Schof

+0

애플과 함께 10.5.8 PPC에 실패하지 않는다. 2.5.1. –

+0

10.5.8 *은 Apple 웹 사이트에 나열된 최신 버전입니다. 10.5.9는 시험판 버전입니까? – Schof

1

여기 내 우분투 리눅스 컴퓨터에서 코드를 테스트했는데 완벽하게 작동했습니다.

시도해 볼만한 제안이 하나 있습니다. 도움이 될지 모르지만 상처를주지는 못합니다. 함께 사용하도록 코드를 다시 작성하십시오 with 문이 파일 객체 상관없이 폐쇄하지됩니다 있는지 확인하도록되어

from __future__ import with_statement 

def worker_tempfile(): 
    tempfd, tempfn = tempfile.mkstemp() 
    with os.fdopen(tempfd, 'wb') as tempobj: 
     tempobj.write('hello, world') 
    os.remove(tempfn) 
    time.sleep(10) 

. 아마도 도움이 될까요?

행운을 빈다. 그건 그렇고, 질문에 좋은 직장.

1

왜 오류가 정품이 아니라고 생각하십니까? 파일을 열 때마다 10000 개의 스레드가 시작되며 Unix 시스템에서는 열려있는 파일의 최대 수는 일반적으로 1024 개입니다.

먼저 현재 열려있는 파일의 수를 수동으로 추적하고 OS 제한을 초과하는지 여부를 확인하십시오.

+0

대략 하나의 함수가 실패 할 때 (worker_tempfile) 대략적으로 동일한 함수가 성공할 때 (worker_notempfile)이 코드가 파이썬 버그 (또는 내 코드의 오류) 일 수 있다고 생각하는 이유가 있습니다. – Schof

+0

매우 약한 이유입니다. 구현이 다른 여러 함수 (builtin os. * 함수 또는 Python 작성 임시 파일. * 함수)를 호출하면 상황이 병렬화되는 방식에 많은 영향을 미칠 수 있습니다. 그래서 오류가 정품이 아닌지 확인해 보시기 바랍니다. –

관련 문제