2017-12-27 26 views
0

내가 가지고있는 원래 스크립트 내에서 별도의 파이썬 스크립트를 실행하는 파이썬 스크립트에 다음 줄 :subprocess.Popen은 (는) 콘솔에 기록 의사 소통을하지만, 파일에 로그인 할 수 없습니다

subprocess.Popen("'/MyExternalPythonScript.py' " + theArgumentToPassToPythonScript, shell=True).communicate() 

위의 줄을 사용하여 , 별도의 Python 파일에있는 문은 주 Python 스크립트의 콘솔에 나타납니다.

그러나이 문은 스크립트가 쓰는 .txt 파일 로그에 반영된 이 아니며은 반영됩니다.

누구든지이를 수정하는 방법을 알고 있으므로 .txt 파일이 메인 파이썬 스크립트의 진정한 콘솔 텍스트를 정확하게 반영 할 수 있습니까?


이 내가 실시간으로 .txt 파일로 콘솔을 저장하기 위해 사용하고 the method이다 : 나는 반드시이 방법에 부착하고 있지 않다

import sys 
class Logger(object): 
    def __init__(self): 
     self.terminal = sys.stdout 
     self.log = open("/ScriptLog.txt", "w", 0) 
    def write(self, message): 
     self.terminal.write(message) 
     self.log.write(message) 


sys.stdout = Logger() 

. 나는 내가 상세히 설명한 것을 달성 할 수있는 방법에 관심이있다.

+0

할 수 있습니다'self.log.flush()'모든 쓰기 후. 기본적으로 파이썬은 버퍼에 충분한 데이터가 있거나 파일 핸들이 닫힐 때까지 (예 : 애플리케이션이 멈출 때까지) 파일에 쓰려고 기다립니다. –

+0

'self.log.write (message)'다음에'self.log.flush()'를 삽입하려고했습니다. 이렇게하면 아무 것도 바뀌지 않았습니다. .txt 파일은 여전히 ​​외부 스크립트의'print' 텍스트를 포함하지 않습니다. – Crickets

+0

잠깐만 요,이 스크립트는 다소 위험합니다. 게다가 당신의 프로그램은 어디에도 인자를 전혀 인쇄하지 않습니다. 그래서 이것은 인수를 인쇄하는 쉘 자체 일 뿐이라고 생각합니다. –

답변

0

subprocess은 새로운 프로세스를 생성하고 부모 프로세스와 통신하지 않습니다 (거의 독립 엔터티 임). 그 이름에도 불구하고 communicate 메서드는 부모 프로세스에서 자식 프로세스로 데이터를 보내거나받는 방법 일뿐입니다 (예 : 사용자가 터미널에서 무언가를 입력하는 것처럼 시뮬레이션)

출력에서는 하위 프로세스가 숫자 (파일 식별자 또는 파일 번호)를 사용합니다. 하위 프로세스가 프로세스를 생성 할 때 자식 프로세스는 표준 출력이 O. 7 (숫자를 말하기 위해) 그러나 그것은 꽤 많이있다. 하위 프로세스는 독립적으로 운영 시스템에 "Hey! 파일 번호 7은 무엇입니까? 나에게 줘"라고 적어 놓았습니다.

는 기본적으로 산란 서브 프로세스가 당신의 Logger 클래스를 이해하지 않는다 (A C fork가 무엇을 이해는 여기에 꽤 도움이된다). 그것은 파일에 내용을 기록해야한다는 것을 알고 있습니다 : 번호로 OS 내에서 고유하게 식별되는 파일이며 달리 지정되지 않는 한 그 번호는 표준 출력의 파일 설명자와 일치합니다 (그러나 # 아래 2, 원하는 경우 변경할 수 있습니다.)

그래서 "솔루션"이 여러 개 있습니다.파일에

  1. 복제 (tee) 표준 출력, 그래서 뭔가가 표준 출력에 기록 될 때, 수술 시스템은 (이 OS 관련이 ... 이건 정말 파이썬은 관련없는) 파일에 기록 :

    import os 
    import tempfile 
    import subprocess 
    
    file_log = os.path.join(tempfile.gettempdir(), 'foo.txt') 
    p = subprocess.Popen("python ./run_something.py | tee %s" % file_log, shell=True) 
    p.wait() 
    
  2. fileno()의 기능을 이용하여 파일을 단말 OR에 기록할지 여부를 선택. (나는 sys.stdout을 덮어 편하지 생각하지 않습니다)

    import os 
    import tempfile 
    import subprocess 
    
    file_log = os.path.join(tempfile.gettempdir(), 'foo.txt') 
    with open(file_log, 'w') as f: 
        p = subprocess.Popen("python ./run_something.py", shell=True, stdout=f.fileno()) 
        p.wait() 
    
  3. 것은 개인적으로 "안전"찾을 내용 : 예를 들어, 파일에 를 작성하는 것만으로 명령을 실행하자 변수에 출력을 저장 및 (부모 프로세스에서) 나중에 데리러 :

    import os 
    import tempfile 
    import subprocess 
    
    p = subprocess.Popen("python ./run_something.py", shell=True, stdout=subprocess.PIPE) 
    p.wait() 
    contents = p.stdout.read() 
    # Whatever the output of Subprocess was is now stored in 'contents' 
    # Let's write it to file: 
    file_log = os.path.join(tempfile.gettempdir(), 'foo.txt') 
    with open(file_log, 'w') as f: 
        f.write(contents) 
    

    이 방법, 당신은 또한 하위 프로세스가 터미널에 "며"무엇이든 출력 코드 어딘가에 print(contents) 할 수 있습니다. 예를 목적으로

는 스크립트 "./run_something.py은"그냥이 :

print("Foo1") 
print("Foo2") 
print("Foo3") 
+0

솔루션 # 3으로 끝났습니다. 그것은 위대한 작품. 나는 간단히'print (contents)'를 할 수 있으며 .txt 로그는'내용'을 반영한다. 자세한 답을 고맙게 생각합니다. – Crickets

+0

물론 ... 그리고 네, 나에게 매우 중요한 것은 _processes_ (스레드가 다른 것)는 기본적으로 파일을 통해 서로 통신 할 수 있다는 것입니다 (하나의 형태 또는 다른 형태로, 그러나 결국에는 파일로) 두 가지 완전히 다른 "것들"을 가지고있는 것처럼 두 가지 공통 파일을 사용하여 "말하기"(대기열이라고 부르거나, 버퍼라고 부름 ... 같은 생각) : 프로세스 -1은 파일에 쓰고 프로세스 2는 그 파일에서 읽습니다. 많은 다른 변형이지만 파일은 프로세스를 함께 "링크"할 수있는 유일한 것입니다. – BorrajaX

1

정말 subprocess.Popen 님의 communicate() 방법이 필요합니까? 당신은 단지 출력을 원하는 것처럼 보입니다. 그것은 subprocess.check_output()을위한 것입니다.

이것을 사용하는 경우 내장 된 logging 모듈을 사용하여 출력 스트림을 여러 대상에 "티"처리 할 수 ​​있습니다.

import logging 
import subprocess 
import sys 

EXTERNAL_SCRIPT_PATH = '/path/to/talker.py' 
LOG_FILE_PATH = '/path/to/debug.log' 

logger = logging.getLogger('') 
logger.setLevel(logging.INFO) 

# Log to screen 
console_logger = logging.StreamHandler(sys.stdout) 
logger.addHandler(console_logger) 

# Log to file 
file_logger = logging.FileHandler(LOG_FILE_PATH) 
logger.addHandler(file_logger) 

# Driver script output 
logger.info('Calling external script') 

# External script output 
logger.info(
    subprocess.check_output(EXTERNAL_SCRIPT_PATH, shell=True) 
) 

# More driver script output 
logger.info('Finished calling external script') 

언제나 shell=True과 조심하십시오. subprocess.check_output(['/path/to/script.py', 'arg1', 'arg2'])으로 전화를 쓸 수 있다면 그렇게하십시오!