[PYTHON] 파이썬 2.6에서 쓰레드 안전 프린트를 얻으려면 어떻게해야합니까?
PYTHON파이썬 2.6에서 쓰레드 안전 프린트를 얻으려면 어떻게해야합니까?
이 기사에 따르면 Python으로 인쇄해도 스레드로부터 안전하지는 않습니다.
Python 3 work-around는 후자의 기사에서 제공됩니다.
파이썬 2.6에서 쓰레드 안전 프린트를 얻으려면 어떻게해야합니까?
해결법
-
==============================
1.재미있는 문제 - softspace 속성의 설정 및 검사를 포함하여 print 문 내에서 발생하는 모든 것을 고려하여 "threadsafe"(실제로는 : 인쇄중인 스레드 만 "표준 출력 제어"를 다른 스레드로 보냄) newline을 출력 할 때 출력되는 모든 전체 라인이 단일 쓰레드로부터 오는 것이 보장되도록) 약간의 어려움이있었습니다 (실제 쓰레드 안전성에 대한 쉬운 접근법 - 별도의 쓰레드를 독점적으로 "소유"하고 핸들링 sys.stdout은 Queue.Queue를 통해 통신합니다. 문제는 스레드 안전성이 아니기 때문에 유용하지는 않습니다 [[일반 인쇄의 경우에도 충돌 위험이없고 표준 출력으로 끝나는 문자가 정확히 인쇄 된]]하지만 확장 된 작업 범위에서 스레드간에 상호 배제가 필요함).
재미있는 문제 - softspace 속성의 설정 및 검사를 포함하여 print 문 내에서 발생하는 모든 것을 고려하여 "threadsafe"(실제로는 : 인쇄중인 스레드 만 "표준 출력 제어"를 다른 스레드로 보냄) newline을 출력 할 때 출력되는 모든 전체 라인이 단일 쓰레드로부터 오는 것이 보장되도록) 약간의 어려움이있었습니다 (실제 쓰레드 안전성에 대한 쉬운 접근법 - 별도의 쓰레드를 독점적으로 "소유"하고 핸들링 sys.stdout은 Queue.Queue를 통해 통신합니다. 문제는 스레드 안전성이 아니기 때문에 유용하지는 않습니다 [[일반 인쇄의 경우에도 충돌 위험이없고 표준 출력으로 끝나는 문자가 정확히 인쇄 된]]하지만 확장 된 작업 범위에서 스레드간에 상호 배제가 필요함).
그래서, 내가 만든 것 같아. :
import random import sys import thread import threading import time def wait(): time.sleep(random.random()) return 'W' def targ(): for n in range(8): wait() print 'Thr', wait(), thread.get_ident(), wait(), 'at', wait(), n tls = threading.local() class ThreadSafeFile(object): def __init__(self, f): self.f = f self.lock = threading.RLock() self.nesting = 0 def _getlock(self): self.lock.acquire() self.nesting += 1 def _droplock(self): nesting = self.nesting self.nesting = 0 for i in range(nesting): self.lock.release() def __getattr__(self, name): if name == 'softspace': return tls.softspace else: raise AttributeError(name) def __setattr__(self, name, value): if name == 'softspace': tls.softspace = value else: return object.__setattr__(self, name, value) def write(self, data): self._getlock() self.f.write(data) if data == '\n': self._droplock() # comment the following statement out to get guaranteed chaos;-) sys.stdout = ThreadSafeFile(sys.stdout) thrs = [] for i in range(8): thrs.append(threading.Thread(target=targ)) print 'Starting' for t in thrs: t.start() for t in thrs: t.join() print 'Done'
대기 호출은이 상호 배제 보증이없는 경우 (주석이있는 경우) 혼돈스럽게 혼합 된 출력을 보장하기위한 것입니다. 파이썬 2.5와 그 이상 (위의 코드는 파이썬 2.5와 그 이상 버전에서 실행될 수 있다고 생각합니다.하지만 쉽게 확인할 수있는 것은 아닙니다). 출력은 다음과 같습니다.
Thr W -1340583936 W at W 0 Thr W -1340051456 W at W 0 Thr W -1338986496 W at W 0 Thr W -1341116416 W at W 0 Thr W -1337921536 W at W 0 Thr W -1341648896 W at W 0 Thr W -1338454016 W at W 0 Thr W -1339518976 W at W 0 Thr W -1340583936 W at W 1 Thr W -1340051456 W at W 1 Thr W -1338986496 W at W 1 ...more of the same...
"직렬화"efect (스레드가 위와 같이 "멋지게 라운드 로빈"하는 것처럼 보임)은 현재 인쇄중인 스레드가 다른 스레드보다 심각하게 느리다는 사실의 부작용입니다 (모두 대기합니다! -). 기다리는 시간을 주석으로 처리하는 대신 출력이 대신 사용됩니다.
Thr W -1341648896 W at W 0 Thr W -1341116416 W at W 0 Thr W -1341648896 W at W 1 Thr W -1340583936 W at W 0 Thr W -1340051456 W at W 0 Thr W -1341116416 W at W 1 Thr W -1341116416 W at W 2 Thr W -1338986496 W at W 0 ...more of the same...
즉,보다 일반적인 "멀티 쓰레드 출력"... 출력의 각 라인이 하나의 단일 쓰레드에서만 제공된다는 보장은 제외합니다.
물론, 'ciao'를 인쇄하는 스레드는 마침내 쉼표없이 인쇄를 수행 할 때까지 표준 출력의 "소유권"을 유지하며, 인쇄를 원하는 다른 스레드는 꽤 오래 동안 잠들 수 있습니다 (그 밖의 방법 출력의 각 줄이 단일 스레드에서 오는 것을 보장 할 수 있습니까? 한 가지 아키텍처는 부분 출력을 실제로 표준 출력에 쓰는 대신 부분 저장소를 스레드에 축적하여 \ n의 수신시에만 쓰기를 수행하는 것입니다. .. 소프트 스페이스 설정으로 적절하게 인터리빙하기 위해 섬세한, 나는 두려워하지만 아마도 가능할 것이다.)
-
==============================
2.문제는 파이썬이 NEWLINE 인쇄와 객체 자체의 인쇄를 위해 별도의 opcode를 사용한다는 것입니다. 가장 쉬운 해결책은 명시 적 줄 바꿈을 사용하여 명시 적 sys.stdout.write를 사용하는 것입니다.
문제는 파이썬이 NEWLINE 인쇄와 객체 자체의 인쇄를 위해 별도의 opcode를 사용한다는 것입니다. 가장 쉬운 해결책은 명시 적 줄 바꿈을 사용하여 명시 적 sys.stdout.write를 사용하는 것입니다.
-
==============================
3.실험을 통해, 나는 다음과 같은 작품이 간단하고 내 요구에 맞는 것을 발견했다.
실험을 통해, 나는 다음과 같은 작품이 간단하고 내 요구에 맞는 것을 발견했다.
print "your string here\n",
또는, 함수에 싸여,
def safe_print(content): print "{0}\n".format(content),
나의 이해는 일반 인쇄의 암시 적 개행이 실제로 다른 인쇄 작업과 경쟁 조건을 일으키는 별도의 작업에서 stdout으로 출력된다는 것입니다. 이 암시 적 newline을 추가 된 문자로 제거하고 문자열에 개행 문자를 포함 시키면이 문제를 피할 수 있습니다.
2017 편집 :이 답변은 약간의 증기를 받기 시작하므로 설명을 원했습니다. 실제로 인쇄물을 "스레드 안전"으로 정확하게 만들지는 않습니다. 인쇄물이 서로 마이크로 초 간격으로 떨어져 있으면 출력물의 순서가 잘못되었을 수 있습니다. 그러나 이것이하는 일은 병행 스레드에서 실행되는 인쇄 명령문에서 오는 왜곡 된 출력을 방지합니다.이 질문은 대부분의 사람들이이 질문을 할 때 실제로 원하는 것입니다.
내 뜻을 나타내는 테스트가 있습니다.
from concurrent.futures import ThreadPoolExecutor def normal_print(content): print content def safe_print(content): print "{0}\n".format(content), with ThreadPoolExecutor(max_workers=10) as executor: print "Normal Print:" for i in range(10): executor.submit(normal_print, i) print "---" with ThreadPoolExecutor(max_workers=10) as executor: print "Safe Print:" for i in range(10): executor.submit(safe_print, i)
산출:
Normal Print: 0 1 23 4 65 7 9 8 ---- Safe Print: 1 0 3 2 4 5 6 7 8 9
-
==============================
4.나는 더 좋은 방법이 잠금 메커니즘이 아니라면 알지 못한다. 그러나 atleast는 쉽게 보입니다. 인쇄가 정말로 스레드 안전하지 않은지 확실하지 않습니다.
나는 더 좋은 방법이 잠금 메커니즘이 아니라면 알지 못한다. 그러나 atleast는 쉽게 보입니다. 인쇄가 정말로 스레드 안전하지 않은지 확실하지 않습니다.
편집 : 좋아, 이제 내 자신을 테스트, 당신 말이 맞아, 당신은 정말 이상한보고 출력을 얻을 수 있습니다. 파이썬 2.7을 사용하기 때문에 미래의 수입은 필요 없습니다.
from __future__ import print_function from threading import Lock print_lock = Lock() def save_print(*args, **kwargs): with print_lock: print (*args, **kwargs) save_print("test", "omg", sep='lol')
from https://stackoverflow.com/questions/3029816/how-do-i-get-a-thread-safe-print-in-python-2-6 by cc-by-sa and MIT license
'PYTHON' 카테고리의 다른 글
[PYTHON] 부동 소수점 오류를 방지하는 방법? (0) | 2018.10.12 |
---|---|
[PYTHON] 다른 목록에 따라 목록을 정렬하는 방법? (0) | 2018.10.12 |
[PYTHON] Selenium Python API 바인딩을 사용하여 Chrome에서 console.log 출력 얻기 (0) | 2018.10.12 |
[PYTHON] UnicodeDecodeError : 'utf8'코덱은 0 위치의 바이트 0xa5을 디코딩 할 수 없습니다 : 잘못된 시작 바이트 (0) | 2018.10.12 |
[PYTHON] 파이썬에서 명시적인 '자아'를 피하는 법? (0) | 2018.10.12 |