IT이야기

'인쇄' 출력을 파일로 리디렉션하는 방법?

cyworld 2022. 3. 12. 10:27
반응형

'인쇄' 출력을 파일로 리디렉션하는 방법?

Python을 사용하여 인쇄를 .txt 파일로 리디렉션하고 싶다.나는 a를 가지고 있다.for어떤 일이 일어날지, 어떤 일이 일어날지 모르는 일이다.print모든 출력을 하나의 파일로 리디렉션하려는 동안 각 .bam 파일에 대한 출력.그래서 나는 다음과 같이 말하려고 했다.

f = open('output.txt','w')
sys.stdout = f

내 대본의 첫머리에그러나 나는 .txt 파일에서 아무것도 얻지 못한다.내 대본은:

#!/usr/bin/python

import os,sys
import subprocess
import glob
from os import path

f = open('output.txt','w')
sys.stdout = f

path= '/home/xxx/nearline/bamfiles'
bamfiles = glob.glob(path + '/*.bam')

for bamfile in bamfiles:
    filename = bamfile.split('/')[-1]
    print 'Filename:', filename
    samtoolsin = subprocess.Popen(["/share/bin/samtools/samtools","view",bamfile],
                                  stdout=subprocess.PIPE,bufsize=1)
    linelist= samtoolsin.stdout.readlines()
    print 'Readlines finished!'

그래서 뭐가 문제야?이것 말고는 다른 방법이 없다.sys.stdout?

내 결과는 다음과 같아야 해:

Filename: ERR001268.bam
Readlines finished!
Mean: 233
SD: 10
Interval is: (213, 252)

이렇게 하는 가장 확실한 방법은 파일 개체로 인쇄하는 것이다.

with open('out.txt', 'w') as f:
    print('Filename:', filename, file=f)  # Python 3.x
    print >> f, 'Filename:', filename     # Python 2.x

그러나 stdout을 리디렉션하는 것도 나에게 효과가 있다.다음과 같은 일회성 스크립트는 아마도 괜찮다.

import sys

orig_stdout = sys.stdout
f = open('out.txt', 'w')
sys.stdout = f

for i in range(2):
    print('i = ', i)

sys.stdout = orig_stdout
f.close()

Python 3.4를 사용하면 표준 라이브러리에 간단한 컨텍스트 관리자가 있으므로

from contextlib import redirect_stdout

with open('out.txt', 'w') as f:
    with redirect_stdout(f):
        print('data')

쉘 자체에서 외부로 리디렉션하는 것도 또 다른 옵션이며, 종종 다음과 같이 선호된다.

./script.py > out.txt

기타 질문:

대본의 첫 번째 파일 이름은 무엇인가?초기화가 안 된 것 같아.

내 첫 번째 추측은 글로브가 어떤 bam files도 찾지 못하기 때문에 for loop이 실행되지 않는다는 것이다.폴더가 있는지 확인하고 스크립트에 bam 파일을 인쇄하십시오.

또한 os.path.join os.path.basename을 사용하여 경로 및 파일 이름을 조작하십시오.

로 인쇄를 리디렉션할 수 있음file에서는 논쟁(피톤 2에서는 논쟁)이.>>대신 연산자).

f = open(filename,'w')
print('whatever', file=f) # Python 3.x
print >>f, 'whatever'     # Python 2.x

대부분의 경우, 너는 보통 파일에 쓰는 것이 더 낫다.

f.write('whatever')

또는, 공백으로 쓰고 싶은 항목이 여러 개 있을 경우,print:

f.write(' '.join(('whatever', str(var2), 'etc')))

Python 2 또는 Python 3 API 참조:

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

파일 인수는 다음이 있는 개체여야 함write(string)방법; 존재하지 않는 경우 또는None가 사용될 것이다.인쇄된 인수는 텍스트 문자열로 변환되므로,print()이진 모드 파일 개체와 함께 사용할 수 없음.이러한 경우에는 다음을 사용하십시오.file.write(...)대신에

파일 개체가 일반적으로 포함되기 때문에write()메소드, 당신이 해야 할 일은 파일 객체를 그 인수에 전달하는 것이다.

파일에 쓰기/덮어쓰기

with open('file.txt', 'w') as f:
    print('hello world', file=f)

파일에 쓰기/적용

with open('file.txt', 'a') as f:
    print('hello world', file=f)

이는 완벽하게 작동한다:

import sys
sys.stdout=open("test.txt","w")
print ("hello")
sys.stdout.close()

이제 그 안부는 시험에 쓰일 것이다.txt 파일반드시 닫으십시오.stdoutA과 함께close, 그것이 없으면 콘텐츠는 파일에 저장되지 않을 것이다.

사용하지 마십시오.print, 사용logging

바꿀 수 있다.sys.stdout파일을 가리키지만, 이것은 이 문제를 다루기 위한 꽤 엉성하고 융통성 없는 방법이다.사용하는 대신print, 모듈을 사용하십시오.

와 함께logging, 당신은 당신이 원하는 대로 인쇄할 수 있다.stdout또는 파일에 출력을 쓸 수도 있다.다른 메시지 수준도 사용할 수 있다.criticalerrorwarninginfodebug예를 들어 콘솔에 주요 문제만 인쇄하고 파일에 마이너 코드 작업을 기록하십시오.

간단한 예

수입logging , , , , , .logger 및 수 리 ::

import logging
logger = logging.getLogger()
logger.setLevel(logging.DEBUG) # process everything, even if everything isn't printed

stdout으로 인쇄하려면:

ch = logging.StreamHandler()
ch.setLevel(logging.INFO) # or any other level
logger.addHandler(ch)

파일에 쓰기를 원하는 경우(마지막 섹션을 건너뛰는 파일에만 쓰려는 경우):

fh = logging.FileHandler('myLog.log')
fh.setLevel(logging.DEBUG) # or any level you want
logger.addHandler(fh)

그럼, 어디에 사용하든print그 중 하나를 사용하다logger방법:

# print(foo)
logger.debug(foo)

# print('finishing processing')
logger.info('finishing processing')

# print('Something may be wrong')
logger.warning('Something may be wrong')

# print('Something is going really bad')
logger.error('Something is going really bad')

고급 사용법에 대해 자세히 알아보려면logging특징, Python 문서의 훌륭한 튜토리얼을 읽어 보십시오.

가장 쉬운 해결책은 비단뱀을 통해서가 아니라 껍데기를 통해서이다.파일의 첫 번째 줄부터(#!/usr/bin/python유닉스 시스템에 접속하셨나 보군그냥 사용해print대본에서 파일을 열지 마십시오.파일을 실행하기 위해 이동할 때

./script.py

파일을 실행하려면 다음을 사용하십시오.

./script.py > <filename>

대체하는 곳<filename>출력할 파일의 이름을 입력하십시오.>토큰은 다음 토큰으로 설명된 파일에 stdout을 설정하도록 셸(대부분)을 알려준다.

여기서 언급되어야 할 한 가지 중요한 것은 "script.py"이 실행 가능하도록 만들어져야 한다는 것이다../script.py뛰다

그래서 달리기 전에./script.py,이 명령을 실행하십시오.

chmod a+x script.py(모든 사용자에 대해 스크립트를 실행 가능하도록 설정)

만약 당신이 Linux를 사용하고 있다면, 나는 당신에게 그것을 사용할 것을 제안한다.tee실행하다. 과 같다구현은 다음과 같다.

python python_file.py | tee any_file_name.txt

만약 당신이 코드의 어떤 것도 바꾸고 싶지 않다면, 나는 이것이 가능한 최선의 해결책이라고 생각한다.로거를 구현할 수도 있지만 코드를 변경해야 한다.

너는 이 대답을 좋아하지 않을지 모르지만, 나는 그것이 맞는 답이라고 생각해.꼭 필요한 경우가 아니면 stdout 목적지를 변경하지 마십시오(stdout에만 출력되는 라이브러리를 사용하고 있을 수도 있음).? 확실히 여기서는 그렇지 않다.

나는 네가 좋은 습관으로서 미리 데이터를 끈으로 준비해서 파일을 열어 한 번에 다 써야 한다고 생각해.파일 핸들을 연 시간이 길수록 이 파일에 오류가 발생할 가능성이 높기 때문이다(파일 잠금 오류, I/O 오류 등).단지 한 번의 수술로 모든 것을 하는 것만으로도 그것이 언제 잘못되었을지 의심할 여지가 없다.

예를 들면 다음과 같다.

out_lines = []
for bamfile in bamfiles:
    filename = bamfile.split('/')[-1]
    out_lines.append('Filename: %s' % filename)
    samtoolsin = subprocess.Popen(["/share/bin/samtools/samtools","view",bamfile],
                                  stdout=subprocess.PIPE,bufsize=1)
    linelist= samtoolsin.stdout.readlines()
    print 'Readlines finished!'
    out_lines.extend(linelist)
    out_lines.append('\n')

그리고 목록 항목당 한 줄씩 "데이터 라인"을 수집하는 작업을 모두 마치면 몇 줄에 가입할 수 있다.'\n'모든 것을 출력할 수 있도록 하는 문자들; 어쩌면 당신의 출력 문구를 다음 문자로 포장할 수도 있다.with블록, 추가 안전(잘못된 경우에도 출력 핸들이 자동으로 닫힘):

out_string = '\n'.join(out_lines)
out_filename = 'myfile.txt'
with open(out_filename, 'w') as outf:
    outf.write(out_string)
print "YAY MY STDOUT IS UNTAINTED!!!"

하지만 쓸 데이터가 많으면 한 번에 한 조각씩 쓸 수 있다.나는 그것이 당신의 신청과 관련이 없다고 생각하지만, 여기 대안이 있다.

out_filename = 'myfile.txt'
outf = open(out_filename, 'w')
for bamfile in bamfiles:
    filename = bamfile.split('/')[-1]
    outf.write('Filename: %s' % filename)
    samtoolsin = subprocess.Popen(["/share/bin/samtools/samtools","view",bamfile],
                                  stdout=subprocess.PIPE,bufsize=1)
    mydata = samtoolsin.stdout.read()
    outf.write(mydata)
outf.close()

리디렉션할 경우stdout당신의 문제를 위해 효과가 있다, 그링고 수아베의 대답은 그것을 어떻게 하는지에 대한 좋은 증명이다.

더욱 쉽게 하기 위해, 나는 컨텍스트매니저를 활용한 버전을 만들었는데, 그 구문을 사용하여 간결하게 일반화된 호출 구문을 만들었다.with문:

from contextlib import contextmanager
import sys

@contextmanager
def redirected_stdout(outstream):
    orig_stdout = sys.stdout
    try:
        sys.stdout = outstream
        yield
    finally:
        sys.stdout = orig_stdout

사용하려면 다음을 수행하십시오(Suave의 예에서 파생됨).

with open('out.txt', 'w') as outfile:
    with redirected_stdout(outfile):
        for i in range(2):
            print('i =', i)

선택적으로 리디렉션하는 데 유용하다.print모듈이 맘에 안 드는 방식으로 사용할 때유일한 단점(그리고 이것은 여러 상황에 대한 거래차단이다)은 한 사람이 다른 가치의 여러 개의 스레드를 원하면 작동하지 않는다는 것이다.stdout그러나 그것은 보다 나은 일반화된 방법을 필요로 한다: 간접 모듈 접근.당신은 이 질문에 대한 다른 답변에서 그것의 구현을 볼 수 있다.

나는 다음과 같은 방법으로 이것을 깨트릴 수 있다.내장 인쇄 기능 대신 이 인쇄 기능을 사용하고 내용을 파일에 저장한다.

from __future__ import print_function
import builtins as __builtin__

log = open("log.txt", "a")

def print(*args):
    newLine = ""
    for item in args:
        newLine = newLine + str(item) + " "
    newLine = (
        newLine
        + """
"""
    )
    log.write(newLine)
    log.flush()
    __builtin__.print(*args)
    return

sys.stdout 값을 변경하면 인쇄할 모든 호출의 대상이 변경된다.다른 방법으로 인쇄의 목적지를 변경하면 같은 결과를 얻을 수 있다.

버그가 다른 곳에 있는 경우:

  • 질문에 대해 삭제한 코드일 수 있음(호출을 열 때 파일 이름은 어디에서 오는가?)
  • 또한 데이터가 플러시되기를 기다리지 않는 경우도 있을 수 있다. 단자에서 인쇄할 경우 새 줄마다 데이터가 플러시되지만 파일로 인쇄할 경우 stdout 버퍼(대부분 시스템의 4096바이트)가 가득 찰 때만 플러시된다.

파이톤 3에서는 재할당 할 수 있다.print:

#!/usr/bin/python3

def other_fn():
    #This will use the print function that's active when the function is called
    print("Printing from function")

file_name = "test.txt"
with open(file_name, "w+") as f_out:
    py_print = print #Need to use this to restore builtin print later, and to not induce recursion
   
    print = lambda out_str : py_print(out_str, file=f_out)
    
    #If you'd like, for completeness, you can include args+kwargs
    print = lambda *args, **kwargs : py_print(*args, file=f_out, **kwargs)
    
    print("Writing to %s" %(file_name))

    other_fn()  #Writes to file

    #Must restore builtin print, or you'll get 'I/O operation on closed file'
    #If you attempt to print after this block
    print = py_print

print("Printing to stdout")
other_fn() #Writes to console/stdout

다음에서 인쇄된 것을 참고하십시오.other_fn인쇄가 글로벌 스코프에서 재할당되고 있기 때문에 출력만 전환한다.만약 우리가 기능 에서 인쇄를 할당한다면, 그 인쇄물은other_fn일반적으로 영향을 받지 않는다.모든 인쇄 호출에 영향을 미치려면 글로벌 키워드를 사용하십시오.

import builtins

def other_fn():
    #This will use the print function that's active when the function is called
    print("Printing from function")

def main():
    global print #Without this, other_fn will use builtins.print
    file_name = "test.txt"
    with open(file_name, "w+") as f_out:

        print = lambda *args, **kwargs : builtins.print(*args, file=f_out, **kwargs)

        print("Writing to %s" %(file_name))

        other_fn()  #Writes to file

        #Must restore builtin print, or you'll get 'I/O operation on closed file'
        #If you attempt to print after this block
        print = builtins.print

    print("Printing to stdout")
    other_fn() #Writes to console/stdout

개인적으로, 나는 그 요구 사항을 무시하는 것을 선호한다.print출력 파일 설명자를 새로운 함수에 구워서 기능한다.

file_name = "myoutput.txt"
with open(file_name, "w+") as outfile:
    fprint = lambda pstring : print(pstring, file=outfile)
    print("Writing to stdout")
    fprint("Writing to %s" % (file_name))

여기 내가 파일/로그에 인쇄하는 데 사용한 다른 방법이 있다.내장된 인쇄 기능을 수정하여 현재 타임스탬프가 있는 임시 디렉토리의 파일에 기록되고 stdout에 인쇄되도록 하십시오.스크립트 내에서 이 작업을 수행할 수 있는 유일한 장점은 기존 인쇄 문장을 수정할 필요가 없다는 것이다.

print('test')
test

원본 인쇄 기능을 새 변수에 복사

og_print = print
og_print('test2')
test2

기존 인쇄 기능 덮어쓰기

def print(*msg):
    '''print and log!'''
    # import datetime for timestamps
    import datetime as dt
    # convert input arguments to strings for concatenation
    message = []
    for m in msg:
        message.append(str(m))
    message = ' '.join(message)
    # append to the log file
    with open('/tmp/test.log','a') as log:
        log.write(f'{dt.datetime.now()} | {message}\n')
    # print the message using the copy of the original print function to stdout
    og_print(message)
print('test3')
test3

파일을 표시하다

cat /tmp/test.log
2022-01-25 10:19:11.045062 | test3

파일을 삭제하다

rm /tmp/test.log

루프용 인쇄 기능을 확장하는 기능

x = 0
while x <=5:
    x = x + 1
    with open('outputEis.txt', 'a') as f:
        print(x, file=f)
    f.close()

참조URL: https://stackoverflow.com/questions/7152762/how-to-redirect-print-output-to-a-file

반응형