2016-09-27 4 views
0

파이썬에서 여러 직렬 포트에서 읽으려고합니다. 그러나 this 스레드와 달리 동적으로 포트 번호를 변경할 수 있기를 원합니다 (명령 행 옵션을 통해 읽음).파이썬 다중 직렬 포트 읽기

나의 생각은 포트를 "포트"파일에 넣고이 파일을 읽고 "포트"의 줄 수에 따라 열린 직렬 포트를 목록에 넣는 것이었다. 내 최소한의 예 :

import numpy as np 
import serial 

p = np.genfromtxt('ports',delimiter=',',dtype=None) 
nser = p.size 

ser = [serial.Serial(port=p[i][0], baudrate=p[i][1]) for i in xrange(nser)] 

"포트"보이는 (순간) 다음

'/dev/ttyUSB0',4800 

오류 :

Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
IndexError: 0-d arrays can't be indexed 

분명히 파일이 제대로 배열로 읽을 수있다 , 그리고 나는 이미 여러 가지 다른 방법과 방법을 시도했다. (pythons 자신의 메서드 나 np.loadtxt를 사용한다.)

누구나 a) 파일을 올바르게 읽고 b) 유용한 방법으로 여러 포트 문제를 해결하는 방법을 알고 있습니까? 미리 감사드립니다.

답변

2

설정 파일 형식은 매우 간단하며 numpy없이 쉽게 파싱 할 수 있습니다. 간단한 문자열 분할을 사용하여 각 포트 정의를로드 할 수 있습니다.

serial_ports = [] 
with open('ports') as f: 
    for line in f: 
     port, baud = line.split(',') 
     serial_ports.append(serial.Serial(port, int(baud))) 

아니면 csv 모듈을 사용할 수 있습니다 : 직렬 포트의 독자 처리 할 방법에 대해 많은 정보를 제공하지 않았기 때문에 질문의 두 번째 부분은 더 어렵습니다


import csv 

with open('ports') as f: 
    serial_ports = [serial.Serial(port, int(baud)) for port, baud in csv.reader(f)] 
포트를 통해 수신 된 데이터

응용 프로그램이 I/O 바운드 인 경우 (대부분의 경우) 직렬 포트에 읽을 데이터가 있으면 비동기식으로 검사 한 다음 필요에 따라 읽을 수 있습니다. select() 모듈을 사용하거나 Python> = 3.4 인 경우 selectors 모듈을 사용하면됩니다. 이 작업을 수행하기 위해 여러 프로세스가 필요하지 않습니다.

응용 프로그램이 CPU 바운드 인 경우 mutiprocessing.Process() 또는 subprocess.Popen()을 사용할 수 있습니다. 부모에서 직렬 포트를 여는 대신 직렬 포트 매개 변수를 자식 함수/프로세스에 대한 인수/명령 줄 인수로 자식에 전달하고 자식이 포트를 열고 데이터를 처리 한 다음 포트를 닫도록합니다.

N.B. 검사되지 않음 - 직렬 포트과 함께 작동하는지 모릅니다. 상위 포트를 열어야하는 경우 하위 프로세스의 표준 포트를 직렬 포트에 연결하십시오. 부모와 자식이 서로에 대해 서로 차단되어있는 프로세스를 교착 상태로 만드는 것이 쉽기 때문에이 작업에주의해야합니다.

from subprocess import Popen, PIPE 

s = serial.Serial(port, baud) 
p = Popen(['python', 'port_reader.py'], stdin=s, stdout=PIPE, stderr=PIPE) 
p.communicate() 

multiprocessing을 사용하는 경우 열려있는 직렬 포트를 자식으로 전달할 수 있습니다. 이게 효과가 있을지도 ...?

from multiprocessing import Process 

def child(port): 
    while True: 
     line = port.readline() 
     if not line: 
      break 
     print('child(): read line: {!r}'.format(line)) 

port = serial.Serial(port, baud) 
p = Process(target=child, args=(port,)) 
p.start() 
p.join() 
1

꽤 명확하게하려고 노력하고 있지만 만약 내가 같은 파일을 가지고 무엇을 이해하지 않았다 :

'/dev/ttyUSB0',4800 
'/dev/ttyUSB1',4801,'/dev/ttyUSB3',4803 

및 목록으로 이동하는 방법을 그것을 저장을 읽고 싶은 것 수 :

with open('ports.txt') as f: 
    lines = f.read().replace('\n', ',') 
print lines 

을 줄 것이다 :

>>> lines 
'/dev/ttyUSB0',4800,'/dev/ttyUSB1',4801,'/dev/ttyUSB3',4803 

하고 분할 할 경우를 정수, 당신은 할 수 : 이제

>>> l1 = [lines.pop(i) for i,j in enumerate(lines) if type(j)==int ] 
>>> l1 
[4800, 4801, 4803] 
>>> lines 
['/dev/ttyUSB0', '/dev/ttyUSB1', '/dev/ttyUSB3'] 

당신이 'np.loadtxt'가 작동하지 않았다 말했다 때문에하는 NumPy와 배열에 파이썬리스트로 변환하는 방법은 다음과 같습니다

>>> lines = ['/dev/ttyUSB0',4800,'/dev/ttyUSB1',4801,'/dev/ttyUSB3',4803] 
>>> 
>>> import numpy as np 
>>> np.asarray(lines) 
array(['/dev/ttyUSB0', '4800', '/dev/ttyUSB1', '4801', '/dev/ttyUSB3', 
     '4803'], 
     dtype='|S12') 

그러나 다시 나는 그것이 당신이 찾고있는 것이라면 확실하지 않습니다.