2014-10-06 4 views
2

두 개의 python 스크립트가 있습니다. object_generator.py는 지정된 객체를 pickle하고 인쇄합니다. 또 다른 스크립트 object_consumer.py는 subprocess.communicate를 통해 첫 번째 스크립트의 출력을 선택하고 pickle.loads를 사용하여 unpickle을 시도합니다. 이 간단한 시나리오 작업을하는 데 문제가 있습니다. 분명히subprocess.communicate를 통해 python 스크립트간에 피클 링 된 객체 출력 전송

object_generator.py

import pickle 
import base64 

o = {'first':1,'second':2,'third':3,'ls':[1,2,3]} 
d = pickle.dumps(o) 
print(d) 

#Various Approaches I had tried, none of which worked. Ignore this part. 
#s = base64.b64decode(d) 
#encoded_str = str(d).encode('ascii') 
#print('encoded str is :') 
#print(encoded_str) 
#decoded_str = encoded_str.decode('ascii') 
#print('decoded str is :') 
#print(decoded_str) 
#unpickled_obj = pickle.loads(bytes(decoded_str)) 
#print(unpickled_obj) 
#print(type(d)) 
#print(codecs.decode(d)) 

object_consumer.py

import pickle 
import subprocess 
import os 

dr = '"' + os.path.dirname(os.path.abspath(__file__)) + '\\object_generator.py"' 

cmd = 'python -u ' + dr 

proc = subprocess.Popen(cmd,stdout=subprocess.PIPE) 

try: 
    outs, errs = proc.communicate(timeout=15) 
except TimeoutExpired: 
    proc.kill() 
    outs, errs = proc.communicate() 

# 'out' at this point is something like this : 
# b"b'\\x80\\x03}q\......x05K\\x03u.'\r\n" 
# DO SOMETHING WITH outs to get back the bytes which can then be 
# unpickled using pickle.loads 

obj = pickle.loads(outs) 
print(obj) 

, 나는 쉽지만 무엇을 수행해야 후행 \ r \ n을 벗겨해야이 내 코드입니다 다음 것?

+0

이 일이 매우 주어진'subprocess' 모듈 방식'.communicate를 (사용 시나리오 작업을 할 수 데에 당신의 노력 목표를 하는가를) ', 또는 당신은 열려 있습니다 '서브 프로세스 (subprocess) '또는 다른 수단을 사용하여 파이썬 프로세스 간 통신 솔루션을 구현할 수 있습니까? – user3666197

+0

나는 subprocess.check_ouput을 시도한 다음 그 didnt 작업이 통신 할 때 옮겼지만 통신을 사용할 수있는 제한이 없다. 나는 이것의 무엇이 잘못되었는지에 대한 설명과 함께 어떤 다른 방법으로도 감사 할 것입니다. –

+0

페이로드 표현/코딩/직렬화/캡슐화/프레이밍 문제와 프로세스 간 통신 문제를 항상 구분하는 것이 좋습니다. 전자의 경우, 신속하고 확장 가능한 프로세스 간 메시징 **에 대한 개요를 얻으려면 유용 할 것입니다. ** ZeroMQ ** (제어 할 수있는 모든 권한을 얻을 수있는 많은 포트, Python 포함) 통신 아키타 입을 분산 된 병렬 처리 프로젝트 요구 사항에 맞춰야합니다. – user3666197

답변

2

여기에 몇 가지 문제가 있습니다. 먼저 bytes 개체를 object_generator.py에 인쇄하고 있습니다. 파이썬 3.x에서는 str(obj)이 호출되어 결과적으로 b'yourbyteshere'이 인쇄됩니다. 당신은 선도 b' 또는 후행 '을 원하지 않습니다. 이 문제를 해결하려면 bytes 개체를 문자열로 인코딩해야합니다. pickle'latin-1' 인코딩을 사용하므로 bytes 개체를 str으로 디코딩하는 데 사용할 수 있습니다. 다른 문제는 Windows에서 기본적으로 sys.stdout에 사용하는 인코딩은 실제로 pickle 문자열을 인쇄하는 것을 지원하지 않는다는 것입니다. 따라서 sys.stdout *의 기본 인코딩을 'latin-1'으로 변경해야하므로 문자열이 올바른 인코딩으로 부모 프로세스에 전달됩니다.

import pickle 
import base64 
import codecs 

o = {'first':1,'second':2,'third':3,'ls':[1,2,3]} 
d = pickle.dumps(o) 
sys.stdout = io.TextIOWrapper(sys.stdout.detach(), encoding='latin-1') 
print(d.decode('latin-1'), end='', flush=True) # end='' will remove that extra \r\n 

이렇게 변경하면 정상적으로 작동합니다.

편집 :

또 다른 옵션은 부모 프로세스에서 'latin-1'PYTHONIOENCODING 환경 변수를 설정하는 것입니다 :

env = os.environ.copy() 
env['PYTHONIOENCODING'] = 'latin-1' 
proc = subprocess.Popen(['python3', 'async2.py'] ,stdout=subprocess.PIPE, env=env) 

* 파이썬에서 sys.stdout 인코딩을 변경하는 방법에 대한 추가 정보를 원하시면 this question를 참조하십시오 3. 여기에 나와있는 두 가지 접근법이 모두 언급되어 있습니다.

+0

그것은 효과가있다. 당신이 대답을 철회하고 수정 사항으로 다시 게시 된 것을 봅니다. 인내와 문제 해결에 감사드립니다. –

+2

@rusticbit 예, 원래의 대답은 Linux에서 정상적으로 작동했지만 Windows에서는 작동하지 않았습니다. Windows에서 사용되는'sys.stdout' 기본 인코딩의 차이점을 잊어 버렸습니다. – dano

+1

@ trusticbit'io' 모듈 [일반적으로'codecs 모듈]보다 우선해야하기 때문에'codecs '대신'io' 모듈을 사용하도록 제 답변을 업데이트했습니다 (https://mail.python.org /pipermail/python-list/2010- December/593460.html). 또한 부모 스크립트에서 문제를 해결할 수있는 방법을 추가했습니다. – dano

1

필자는 기본 파일이 살아 있어야하며 속도가 느려야하므로 기본 파일과 외부 파일을 인식하지 못하도록 제안하지 않습니다. 내가 마샬 모듈을 사용

이 당신에게 시간을 절약 할 희망 : https://github.com/jstar88/pyCommunicator

관련 문제