파이썬에서 stderr로 인쇄하는 방법?


1339

stderr에 쓰는 몇 가지 방법이 있습니다.

# Note: this first one does not work in Python 3
print >> sys.stderr, "spam"

sys.stderr.write("spam\n")

os.write(2, b"spam\n")

from __future__ import print_function
print("spam", file=sys.stderr)

그것은 zen의 Python # 13 과 모순되는 것 같습니다. 여기서 차이점은 무엇이며 어떤 방법 으로든 장단점이 있습니까? 어떤 방법을 사용해야합니까?

명백한 방법이 있어야합니다.


46
첫 번째 방법은 파이썬 3에서 제거 된 많은 것들 중 하나입니다. >> 구문은 어쨌든 추악했고, print는 이제 함수이므로 구문은 작동하지 않을 것입니다.
Steve Howard

23
내가 사용 : sys.exit를 ( '오류 : <오류 텍스트>')
스탁

1
그냥 인쇄를 사용하십시오.
PythonMaster202

답변:


1165

나는 이것이 유일하게 짧은 + 유연 + 휴대용 + 읽기 가능하다는 것을 알았습니다.

from __future__ import print_function
import sys

def eprint(*args, **kwargs):
    print(*args, file=sys.stderr, **kwargs)

이 기능 eprint은 표준 print기능 과 동일한 방식으로 사용할 수 있습니다 .

>>> print("Test")
Test
>>> eprint("Test")
Test
>>> eprint("foo", "bar", "baz", sep="---")
foo---bar---baz

29
한 가지 생각 : 인쇄 기능을 가져 오므로 원본 스크립트의 다른 모든 "인쇄"는 "("및 ")"를 추가하여 "기능화"되어야합니다. 따라서이 방법 인 IMO에 약간의 타격이 있습니다.
Dan H

45
예 @DanH이 당신은 당신의 코드 Python3이 준비 확인합니다. 나는 이것이 많은 사람들이 실제로 그것을 좋아하는 이유 일 수 있다고 생각합니다!
MarcH

18
@ MarkH ... 그렇습니다. 파이썬 3 코드를 작성하도록 강요합니다 ... 지금 당신은 그것을 강제로 stderr에 디버깅 정보를 인쇄하기 위해 지금 강요합니다. 내가 무언가를 디버깅하려고 할 때 대부분의 상황. (나는 새로운 구문 오류를 도입하지 않겠다!) :-)
Dan H

29
이 코드 print 전체 프로그램에서 함수 버전을 사용하도록 강요 하지 않습니다 . 의 정의를 포함하는 모듈에서만 eprint(). 파일을 작은 파일에 eprint넣고 다른 파일로 가져 와서 print원하는만큼 명령문 을 계속 사용할 수 있습니다 .
Alexis

3
또한 인쇄에서 인쇄 기능으로 변환하는 것은 2to3가 이미 자동으로 대체하는 간단한 찾기 바꾸기입니다. 당신이하지 않은 경우에 이미 그것을; python2는 2 년 안에 사라질 것입니다 ... 2와 3 사이의 어떤 것들은 약간 까다로울 수 있습니다. 인쇄 기능은 그중 하나가 아닙니다. 참조 docs.python.org/2/library/2to3.html
bobpaul

549
import sys
sys.stderr.write()

내 선택, 더 읽기 쉽고 정확하게 당신이하려는 일과 버전간에 이식 가능하다는 것을 말하십시오.

편집 : 'pythonic'이라는 것은 가독성과 성능에 대한 세 번째 생각입니다 ...이 두 가지를 염두에두고 파이썬을 사용하면 코드의 80 %가 파이썬입니다. 목록 이해력은 자주 사용되지 않는 (가독성) '큰 것'입니다.


88
플러시하는 것을 잊지 마십시오.
temoto

10
print문장의 장점은 문자열이 아닌 값을 먼저 변환하지 않고도 쉽게 인쇄 할 수 있다는 것입니다. 만약 당신이 print 서술문을 필요로한다면, 나는 3 번째 옵션을 사용하여 python 3 ready
vdboor

56
sys.stderr.write()같은 것 print입니다. 개행을 추가하지 않습니다.
대령 패닉

41
@temoto-stderr는 버퍼링되지 않으므로 플러시 할 필요가 없습니다.
Matt

11
@SkipHuffman 당신은 의미한다 os.linesep. 이것은 stderr결국 우리가 말하는 것입니다. 콘솔이 잘못된 줄 바꿈으로 엉망이되지 않도록하십시오.
jpmc26

180

print >> sys.stderrPython3에서 사라졌습니다. http://docs.python.org/3.0/whatsnew/3.0.html 말한다 :

Old: print >> sys.stderr, "fatal error"
New: print("fatal error", file=sys.stderr)

우리 중 많은 사람들에게, 목적지를 지휘의 끝까지 이끄는 것은 다소 부자연 스럽습니다. 대안

sys.stderr.write("fatal error\n")

더 객체 지향적이며 일반에서 특정으로 우아하게 이동합니다. 그러나 write이는 1 : 1 대체품이 아닙니다 print.


5
나는 그것이 선호의 문제라고 생각하지만, 추악한 것이 보이지 않습니다 print('spam', file=sys.stderr). 반복해서 수행하는 경우 가장 인기있는 답변처럼 'eprint'기능을 코딩 할 수 있지만이 경우 로깅에 어떤 문제가 있습니까? stackoverflow.com/a/41304513/1450294
Michael Scheper

의도를 명확히하는 또 다른 방법은 with sys.stderr as dest:들여 쓰기를하기 전에하는 것입니다print("ERROR", file=dest)
MarkHu

130

logging아직 언급 한 사람 은 없지만 오류 메시지를 전달하기 위해 로깅이 특별히 생성되었습니다. 기본 구성은 stderr에 쓰는 스트림 핸들러를 설정합니다.

이 스크립트는 :

# foo.py
import logging

logging.basicConfig(format='%(message)s')
log = logging.getLogger(__name__)
log.warning('I print to stderr by default')
print('hello world')

명령 행에서 실행할 때 다음과 같은 결과가 나타납니다.

$ python3 foo.py > bar.txt
I print to stderr by default

bar.txt라는이 표준 출력에 인쇄 된 '안녕하세요 세계'가 포함됩니다.


2
내 경험상 로깅을 사용하는 것보다 인쇄를 사용하여 메시지를 기록하는 사람이 더 많습니다. python4는 언어에서 인쇄를 제거하고 로깅을 사용해야한다고 생각합니다.
Mnebuerquo

1
이것은 최고의 답변입니다! ... 나는 인쇄 또는 시스템 문제로 고생하고 있거나 알고 ... 누가 적절한 로깅이 필요한지 ... 좋은 생각에 감사드립니다
Carlos Saltos

129

들어 파이썬이 내 선택이 될 것입니다 : print >> sys.stderr, 'spam' 당신은 단순히 문자열로 변환이없이 등 목록 / dicts을 인쇄 할 수 있기 때문에. print >> sys.stderr, {'spam': 'spam'} 대신에: sys.stderr.write(str({'spam': 'spam'}))


6
사전을 인쇄하는 더 파이썬적인 방법은 "{0}".format({'spam': 'spam'})어쨌든 같은 것입니다. 명시 적으로 문자열로 변환하지 말아야한다고 말하고 싶습니다. 편집 : 실수로 문법
luketparkinson

1
@luketparkinson 디버깅에 관한 모든 것-가능한 한 가장 간단한 코드를 사용하는 것이 더 바람직하다고 생각합니다.
Frankovskyi Bogdan

88
Python 3에서는 작동하지 않으므로 새 코드에서는 피해야합니다.
JonnyJD

33

파이썬 3을 사용하여 다음을 수행했습니다.

from sys import stderr

def print_err(*args, **kwargs):
    print(*args, file=stderr, **kwargs)

이제 캐리지 리턴을 피하기 위해 키워드 인수를 추가 할 수 있습니다.

print_err("Error: end of the file reached. The word ", end='')
print_err(word, "was not found")

2
나는 당신도 부분을 사용할 수 있다고 제안하려고했지만, 부분은 부분을 만들 때 stderr를 함수에 할당한다는 것을 깨달았습니다. 이렇게하면 부분적으로 원래 stderr 객체가 유지되므로 나중에 stderr을 리디렉션하지 못하게됩니다.
Rebs

31

첫 번째 접근 방식은 다음과 같습니다.

print >> sys.stderr, 'spam' 

은 "한...입니다 분명 이 할 수있는 방법"다른 사람은 규칙 # 1 만족하지 않는 ( "아름다운 더 추한 이상입니다.")


109
의견이 다릅니다. 이것은 나에게 가장 명백 하지 않습니다.
porgarmingduod

4
@AliVeli 괄호가 없습니다. 이것은 오래된 Python <= 2 구문이므로 Python 3과 호환되지 않습니다.
Rebs

30
나는 이것이 3
화산

4
>>그것이 구문 적으로 무엇을 의미합니까? 나는 bash 's를 복사하는 것이 노력이라는 것을 이해한다 >. 그래서 그렇게하는 것이 구두의 구문입니까?
Dmytro Sirenko

2
@EarlGray 그것은 C ++의 스트림 삽입 연산자로부터의 인수입니다.std::cout << "spam";
Sean Allred

19

이것은 표준 인쇄 기능을 모방하지만 stderr에서 출력합니다.

def print_err(*args):
    sys.stderr.write(' '.join(map(str,args)) + '\n')

8
sys.stderr.flush ()를 추가합니다
AMS

4
@AMS-왜? print플러시를 포함하지 않습니다.
Robᵩ

4
실제로 할 수있을 때 왜 모방합니까?
Mad Physicist

19

파이썬 3에서는 print ()를 사용할 수 있습니다 :

print(*objects, sep=' ', end='\n', file=sys.stdout, flush=False)

거의 즉시 사용 가능 :

import sys
print("Hello, world!", file=sys.stderr)

또는:

from sys import stderr
print("Hello, world!", file=stderr)

이것은 간단하며 그 외에는 아무것도 포함 할 필요가 없습니다 sys.stderr.


16

편집하다 뒤늦게 보면, sys.stderr 변경과 혼동 될 수 있고 동작이 업데이트되는 것을 보지 않으면 다른 사람들이 지적한 것처럼 간단한 함수를 사용하는 것만 큼이 답변이 좋지 않다고 생각합니다.

부분 만 사용하면 한 줄의 코드 만 저장됩니다. 잠재적 혼란은 한 줄의 코드를 절약 할 가치가 없습니다.

기발한

더 쉽게 만들기 위해 '부분'을 사용하는 버전이 있습니다.이 기능은 랩핑 기능에 큰 도움이됩니다.

from __future__ import print_function
import sys
from functools import partial

error = partial(print, file=sys.stderr)

그런 다음 그렇게 사용하십시오

error('An error occured!')

다음을 수행하여 stderr이 아닌 stderr로 인쇄되고 있는지 확인할 수 있습니다 ( http://coreygoldberg.blogspot.com.au/2009/05/python-redirect-or-turn-off-stdout-and 에서 오버라이드 코드 .html ) :

# over-ride stderr to prove that this function works.
class NullDevice():
    def write(self, s):
        pass
sys.stderr = NullDevice()

# we must import print error AFTER we've removed the null device because
# it has been assigned and will not be re-evaluated.
# assume error function is in print_error.py
from print_error import error

# no message should be printed
error("You won't see this error!")

이것의 단점은 부분적 으로 생성시 래핑 된 함수에 sys.stderr의 값을 할당 하는 것입니다. 즉, 나중에 stderr을 리디렉션하면이 기능에 영향을 미치지 않습니다. stderr을 경로 재 지정하려는 경우이 페이지에서 aaguirre가 언급 한 ** kwargs 메소드를 사용 하십시오.


Corey Goldberg의 코드는 Rube Goldberg 시스템에서 가장 잘 실행됩니까? : P
Agi Hammerthief

1
BTW : "커링"은 "부분"에 대해 더 알고 싶다면 유용한 검색 키워드입니다.
MarcH

5

표준 출력에도 동일하게 적용됩니다.

print 'spam'
sys.stdout.write('spam\n')

다른 답변에서 언급했듯이 print 는 종종 편리한 (예 : 디버그 정보 인쇄) 편리한 인터페이스를 제공하지만 쓰기 는 더 빠르며 특정 방식으로 출력 형식을 정확하게 지정해야 할 때 더 편리합니다. 유지 관리도 고려할 것입니다.

  1. 나중에 stdout / stderr과 일반 파일간에 전환하기로 결정할 수 있습니다.

  2. Python 3에서는 print () 구문이 변경되었으므로 두 버전을 모두 지원해야하는 경우 write () 가 더 좋습니다.


4
사용 from __future__ import print_function하는 것이 Python 2.6 이상과 Python 3을 모두 지원하는 더 좋은 방법입니다.
phoenix

4

파이썬 3.4.3에서 일하고 있습니다. 나는 여기에 어떻게 왔는지 보여주는 작은 타이핑을 자르고 있습니다.

[18:19 jsilverman@JSILVERMAN-LT7 pexpect]$ python3
>>> import sys
>>> print("testing", file=sys.stderr)
testing
>>>
[18:19 jsilverman@JSILVERMAN-LT7 pexpect]$ 

작동 했습니까? stderr을 파일로 리디렉션하고 어떤 일이 발생하는지 확인하십시오.

[18:22 jsilverman@JSILVERMAN-LT7 pexpect]$ python3 2> /tmp/test.txt
>>> import sys
>>> print("testing", file=sys.stderr)
>>> [18:22 jsilverman@JSILVERMAN-LT7 pexpect]$
[18:22 jsilverman@JSILVERMAN-LT7 pexpect]$ cat /tmp/test.txt
Python 3.4.3 (default, May  5 2015, 17:58:45)
[GCC 4.9.2] on cygwin
Type "help", "copyright", "credits" or "license" for more information.
testing

[18:22 jsilverman@JSILVERMAN-LT7 pexpect]$

글쎄, 파이썬이 당신에게주는 작은 소개가 stderr로 비난되었다는 사실 외에도 (다른 곳으로 갈 것인가?) 작동합니다.


2

간단한 테스트를 수행하는 경우 :

import time
import sys

def run1(runs):
    x = 0
    cur = time.time()
    while x < runs:
        x += 1
        print >> sys.stderr, 'X'
    elapsed = (time.time()-cur)
    return elapsed

def run2(runs):
    x = 0
    cur = time.time()
    while x < runs:
        x += 1
        sys.stderr.write('X\n')
        sys.stderr.flush()
    elapsed = (time.time()-cur)
    return elapsed

def compare(runs):
    sum1, sum2 = 0, 0
    x = 0
    while x < runs:
        x += 1
        sum1 += run1(runs)
        sum2 += run2(runs)
    return sum1, sum2

if __name__ == '__main__':
    s1, s2 = compare(1000)
    print "Using (print >> sys.stderr, 'X'): %s" %(s1)
    print "Using (sys.stderr.write('X'),sys.stderr.flush()):%s" %(s2)
    print "Ratio: %f" %(float(s1) / float(s2))

sys.stderr.write ()가 지속적으로 1.81 배 빠릅니다!


이것을 실행하면 훨씬 작은 차이가 나타납니다. 대부분의 답변이 인쇄 기능 (파이썬 3)을 무시한다는 것은 흥미 롭습니다. 전에는 사용하지 않았지만 (관성)이 타이밍 스크립트를 실행하고 인쇄 기능을 추가한다고 생각했습니다. 인쇄 문과 함수를 직접 비교하는 것은 불가능합니다 ( 향후 부터 가져 오기 가 전체 파일에 적용되고 인쇄 문을 마스크 함).이 코드를 다시 작성하여 문 대신 인쇄 기능을 사용하면 속도가 더 빠릅니다 (약 1.6에서 약간 가변적 임) ) 인쇄 기능을 선호합니다.
hamish

1
이 테스트의 결과는 오해의 소지가 있습니다. 'X'대신 'XXXXXXXXXXXXXXXXXXXX'를 인쇄하면 비율이 1.05로 떨어집니다 . 필자는 대부분의 파이썬 프로그램이 하나 이상의 문자를 인쇄해야한다고 가정합니다.
항상 묻는 질문 :

14
경고 인쇄와 같은 성능에 대해서는 신경 쓰지 않습니다.
wim

나는 그것이 오래되었다는 것을 알고 있지만, 당신은 내 게시물 이후에도 똑같이 대답했다. ">>"문자. 이 sys.stdout 네임 스페이스가 너무 길면 이름을 바꿀 수 있습니다 (예 : sys import stderr에서 stderr_fh로). 그러면 stderr_fh.write ( "blah")
ThePracticalOne

1
[3/3]이 벤치 마크가 더 정확하더라도 걱정할 가치가 없습니다. Knuth는 다음과 같이 썼다. "프로그래머들은 프로그램의 중요하지 않은 부분의 속도에 대해 생각하거나 걱정하는 데 많은 시간을 낭비하며, 이러한 효율성에 대한 시도는 실제로 디버깅 및 유지 관리를 고려할 때 강력한 부정적인 영향을 미칩니다. 효율성은 시간의 약 97 %라고 말합니다. 조기 최적화는 모든 악의 근원입니다. "
Corey Goldberg

1

치명적인 오류로 인해 프로그램을 종료하려면 다음을 사용하십시오.

sys.exit("Your program caused a fatal error. ... description ...")

import sys헤더한다.


-2

질문에 대한 대답은 : 파이썬에서 stderr를 인쇄하는 다른 방법이 있지만 1) 우리가 사용하는 Python 버전 2.) 우리가 원하는 정확한 출력에 따라 다릅니다.

print와 stderr의 쓰기 기능의 차이점 : stderr : stderr (표준 오류)는 모든 UNIX / Linux 시스템에 내장 된 파이프로, 프로그램이 충돌하고 디버깅 정보 (Python의 역 추적과 같은)를 인쇄 할 때 stderr로 이동합니다. 파이프.

인쇄 : print는 입력을 형식화하는 래퍼 (입력은 인수와 끝의 줄 바꿈 사이의 공간 임)이며 주어진 객체의 write 함수를 호출합니다. 주어진 객체는 기본적으로 sys.stdout입니다. 파일을 전달하십시오. 즉 파일에 입력을 인쇄 할 수도 있습니다.

Python2 : python2를 사용하는 경우

>>> import sys
>>> print "hi"
hi
>>> print("hi")
hi
>>> print >> sys.stderr.write("hi")
hi

Python2의 후행 쉼표는 Python3에서 매개 변수가되므로 인쇄 후 줄 바꿈을 피하기 위해 후행 쉼표를 사용하면 Python3에서는 파이썬 2에서 구문 오류 인 print ( 'Text to print', end = '')처럼 보입니다. .

http://python3porting.com/noconv.html

python3에서 위의 시나리오를 확인하면 :

>>> import sys
>>> print("hi")
hi

파이썬 2.6에서는 함수로 인쇄하기 위해 앞으로 가져 오기가 있습니다. 따라서 구문 오류 및 기타 차이점을 피하려면 향후 import print_function 에서 print ()를 사용하는 파일을 시작해야합니다 . 미래의 수입은 파이썬 2.6에서 작동 이상, 그래서 파이썬 2.5 및 이전 버전 두 가지 옵션이 있습니다. 보다 복잡한 인쇄물을 더 간단한 것으로 변환하거나 Python2 및 Python3에서 작동하는 별도의 인쇄 기능을 사용할 수 있습니다.

>>> from __future__ import print_function
>>> 
>>> def printex(*args, **kwargs):
...     print(*args, file=sys.stderr, **kwargs)
... 
>>> printex("hii")
hii
>>>

사례 : sys.stderr.write () 또는 sys.stdout.write () (stdout (표준 출력)는 모든 UNIX / Linux 시스템에 내장 된 파이프 임)는 인쇄를 대체하지 않지만, 예 경우에 따라 대안으로 사용할 수 있습니다. 인쇄는 끝에 공백과 줄 바꿈으로 입력을 감싸고 쓰기 기능을 사용하여 쓰는 래퍼입니다. 이것이 sys.stderr.write ()가 더 빠른 이유입니다.

참고 : 로깅을 사용하여 추적 및 디버깅 할 수도 있습니다.

#test.py
import logging
logging.info('This is the existing protocol.')
FORMAT = "%(asctime)-15s %(clientip)s %(user)-8s %(message)s"
logging.basicConfig(format=FORMAT)
d = {'clientip': '192.168.0.1', 'user': 'fbloggs'}
logging.warning("Protocol problem: %s", "connection reset", extra=d)

https://docs.python.org/2/library/logging.html#logger-objects

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.