Read (os.read) FIFO non-blockingly without fixed buffer size - python-2.7

In this question, the asker has addressed the problem of reading from a named pipe in a non-blocking manner, but he uses a fixed buffer size. Is there a way to do this without a fixed buffer size and just waiting for the other end to terminate their own buffer with a newline character?

Assuming that your delimiter is a you can read multiple variable length strings in a non-blocking manner, as shown in this program which counts while receiving output from a named pipe.
import os
import time
import errno
import sys
io = os.open(expanduser("~/named_pipes/cob_input"), os.O_RDONLY | os.O_NONBLOCK)
# For implementing non-blocking IO
def read_pipe_non_blocking(input_pipe, size):
try:
in_buffer = os.read(input_pipe, size)
except OSError as err:
if err.errno == errno.EAGAIN or err.errno == errno.EWOULDBLOCK:
in_buffer = None
else:
raise # something else has happened -- better reraise
return in_buffer
def get_azimuth(input_pipe):
in_buffer = read_pipe_non_blocking(input_pipe, 1)
print(in_buffer)
if(in_buffer is None):
sys.stderr.write("n")
return ""
else:
tmp_buffer = None
while(tmp_buffer != "a"):
sys.stderr.write("m")
time.sleep(0.1)
tmp_buffer = read_pipe_non_blocking(input_pipe, 1)
if(tmp_buffer != None and tmp_buffer != "a"):
in_buffer += tmp_buffer
read_pipe_non_blocking(input_pipe, 1) #Read in the newline character and the toss it
sys.stderr.write("\nReturning \{%s\}" %in_buffer)
return in_buffer
i = 0
while 1:
print i
time.sleep(1)
i += 1
get_azimuth(io)
This code has been directly copy pasted from my code and isn't really that clear. If anyone needs clarification, leave a comment.

Related

Error while closing the python serial port

" i am trying to read data from the serial connection and doing some stuff if it matches my string but its giving me errors when i close the serial connection port"
" for some reason i do not see this error if i use the serial.readline() method "
import time
import serial
from Queue import Queue
from threading import Thread
class NonBlocking:
def __init__(self, serial_connection, radio_serial_connection):
self._s = serial_connection
self._q = Queue()
self.buf = bytearray()
def _populateQueue(serial_connection, queue):
if type(serial_connection) == str:
return
self.s = serial_connection
while True:
i = self.buf.find(b"\n")
if i >= 0:
r = self.buf[:i + 1]
self.buf = self.buf[i + 1:]
queue.put(r)
while True:
i = max(1, min(2048, self.s.in_waiting))
data = self.s.read(i)
i = data.find(b"\n")
if i >= 0:
r = self.buf + data[:i + 1]
self.buf[0:] = data[i + 1:]
a = r.split('\r\n')
for item in a:
if item:
queue.put(item)
else:
self.buf.extend(data)
self._t = Thread(target=_populateQueue, args=(self._s, self._q))
self._t.daemon = True
self._t.start()
def read_all(self, timeout=None):
data = list()
if self._q.empty():
pass
while not self._q.empty():
data.append(self._q.get(block=timeout is not None, timeout=timeout))
return data
class SerialCommands:
def __init__(self, port, baudrate):
self.serial_connection = serial.Serial(port, baudrate)
self.queue_data = NonBlocking(self.serial_connection, '')
def read_data(self):
returned_info = self.queue_data.read_all()
return returned_info
def close_q(self):
self.serial_connection.close()
class qLibrary:
def __init__(self):
self.q = None
self.port = None
def close_q_connection(self):
self.q.close_q()
def establish_connection_to_q(self, port, baudrate=115200, delay=2):
self.delay = int(delay)
self.port = port
try:
if not self.q:
self.q = SerialCommands(self.port, int(baudrate))
except IOError:
raise AssertionError('Unable to open {0}'.format(port))
def verify_event(self, data, timeout=5):
timeout = int(timeout)
data = str(data)
# print data
while timeout:
try:
to_analyze = self.q.read_data()
for item in to_analyze:
print "item: ", item
if str(item).find(str(data)) > -1:
print "Found data: '{0}' in string: '{1}'".format(data, item)
except:
pass
time.sleep(1)
timeout -= 1
if __name__ == '__main__':
q1 = qLibrary()
q1.establish_connection_to_q('COM5')
q1.verify_event("ATE")
q1.close_q_connection()
" i expect the code to close the serial connection without any exceptions or errors "
the output is
Exception in thread Thread-1:
Traceback (most recent call last):
File "C:\Python27\Lib\threading.py", line 801, in __bootstrap_inner
self.run()
File "C:\Python27\Lib\threading.py", line 754, in run
self.__target(*self.__args, **self.__kwargs)
File "C:/Program Files (x86)/serialtest1.py", >line 27, in _populateQueue
data = self.s.read(i)
File "C:\Program Files (x86)\venv\lib\site->packages\serial\serialwin32.py", line 283, in read
ctypes.byref(self._overlapped_read))
TypeError: byref() argument must be a ctypes instance, not 'NoneType'
If you define your serial port with no timeout it will get the default setting timeout=None which means when you call serial.read(x) the code will block until you read x bytes.
If you never get those x bytes your code will get stuck in there waiting forever, or at least until you receive more data on the buffer to get the total number of bytes received equal to x.
If you mix that up with threading, I'm afraid you are quite likely closing the port while you are trying to read.
You can probably fix this issue just defining a sensible read timeout on your port or changing the way you read. The general advice is to set a timeout that works for your application and read at least the maximum number of bytes you expect. Reading your code, that seems to be what you wanted to do. If so, you forgot to set the timeout.
If you have a reason not to set a timeout or you want to keep your reading routine as it is, you can make your code work if you cancel reading before closing. You can do that with serial.cancel_read()

Python2.7: reading a gzfile content inside a zipfile

Hello I was wondering if there is a way of reading a unformatted file which is stored in gzformat that is stored in zipformat. also this should be done without extracting any file format and outside pluggin than what python 2.7 can provides.
I just want to read entire or line (depending on minimal for memory usage) of the content if there is a bunch of gz in a zipfile then store it in a txt format outside.
My code as of now can read out .log, .gz, .zip also .zip in a zip.
the idea is that it should repeat itself until we get the main file !
Thanks in advance :=)
.zip--->.gz--->unformattedfile
def decompress_file(filepath,type,file=None):
result = {}
if type.lower() == '.log':
if file ==None:
inFile = open(filepath, 'r')
return getLog(inFile)
else:
return getLog(file)
if type.lower() == '.gz':
if file == None:
inFile = gzip.open(filepath, "r")
else:
#content = io.BytesIO(file.read())
with file:
Gz_file= open(file,'r')
for gzFiles in file.namelist():
zFile=file.getinfo(file)
return getLog(zFile)
return getLog(inFile)
print inFile
return getLog(inFile)
if type.lower() == '.zip':
if file == None:
with zip.ZipFile(filepath,'r'):
zFile = zip.ZipFile(filepath)
else:
with zip.ZipFile(file,'r'):
zFile = zip.ZipFile(file)
for f_list in zFile.namelist():
content= io.BytesIO(zFile.read(f_list))
pattern = r'(.+)(?P<file>\.zip|\.gz)'
rgz = re.compile(pattern, re.IGNORECASE)
m = rgz.match(f_list)
if m==None:
type = '.log'
decompress_file(f_list,type,zFile)
else:
decompress_file(f_list,m.group('file').lower(),content)
return result
return result
if __name__ == '__main__':
decompress_file("filepath",'.zip' )

Python Twisted sending large a file across network

I am trying to send a file across the network using Twisted with the LineReceiver protocol. The issue I am seeing is that when I read a binary file and try to send the chunks they simply don't send.
I am reading the file using:
import json
import time
import threading
from twisted.internet import reactor, threads
from twisted.protocols.basic import LineReceiver
from twisted.internet import protocol
MaximumMsgSize = 15500
trySend = True
connectionToServer = None
class ClientInterfaceFactory(protocol.Factory):
def buildProtocol(self, addr):
return WoosterInterfaceProtocol(self._msgProcessor, self._logger)
class ClientInterfaceProtocol(LineReceiver):
def connectionMade(self):
connectionToServer = self
def _DecodeMessage(self, rawMsg):
header, body = json.loads(rawMsg)
return (header, json.loads(body))
def ProcessIncomingMsg(self, rawMsg, connObject):
# Decode raw message.
decodedMsg = self._DecodeMessage(rawMsg)
self.ProccessTransmitJobToNode(decodedMsg, connObject)
def _BuildMessage(self, id, msgBody = {}):
msgs = []
fullMsgBody = json.dumps(msgBody)
msgBodyLength = len(fullMsgBody)
totalParts = 1 if msgBodyLength <= MaximumMsgSize else \
int(math.ceil(msgBodyLength / MaximumMsgSize))
startPoint = 0
msgBodyPos = 0
for partNo in range(totalParts):
msgBodyPos = (partNo + 1) * MaximumMsgSize
header = {'ID' : id, 'MsgParts' : totalParts,
'MsgPart' : partNo }
msg = (header, fullMsgBody[startPoint:msgBodyPos])
jsonMsg = json.dumps(msg)
msgs.append(jsonMsg)
startPoint = msgBodyPos
return (msgs, '')
def ProccessTransmitJobToNode(self, msg, connection):
rootDir = '../documentation/configs/Wooster'
exportedFiles = ['consoleLog.txt', 'blob.dat']
params = {
'Status' : 'buildStatus',
'TaskID' : 'taskID',
'Name' : 'taskName',
'Exports' : len(exportedFiles),
}
msg, statusStr = self._BuildMessage(101, params)
connection.sendLine(msg[0])
for filename in exportedFiles:
with open (filename, "rb") as exportFileHandle:
data = exportFileHandle.read().encode('base64')
params = {
ExportFileToMaster_Tag.TaskID : taskID,
ExportFileToMaster_Tag.FileContents : data,
ExportFileToMaster_Tag.Filename : filename
}
msgs, _ = self._BuildMessage(MsgID.ExportFileToMaster, params)
for m in msgs:
connection.sendLine(m)
def lineReceived(self, data):
threads.deferToThread(self.ProcessIncomingMsg, data, self)
def ConnectFailed(reason):
print 'Connection failed..'
reactor.callLater(20, reactor.callFromThread, ConnectToServer)
def ConnectToServer():
print 'Connecting...'
from twisted.internet.endpoints import TCP4ClientEndpoint
endpoint = TCP4ClientEndpoint(reactor, 'localhost', 8181)
deferItem = endpoint.connect(factory)
deferItem.addErrback(ConnectFailed)
netThread = threading.Thread(target=reactor.run, kwargs={"installSignalHandlers": False})
netThread.start()
reactor.callFromThread(ConnectToServer)
factory = ClientInterfaceFactory()
protocol = ClientInterfaceProtocol()
while 1:
time.sleep(0.01)
if connectionToServer == None: continue
if trySend == True:
protocol.ProccessTransmitJobToNode(None, None)
trySend = False
Is there something I am doing wrong?file is sent, it's when the write is multi part or there are more than one file it struggles.
If a single write occurs then the m
Note: I have updated the question with a crude piece of sample code in the hope it makes sense.
_BuildMessage returns a two-tuple: (msgs, '').
Your network code iterates over this:
msgs = self._BuildMessage(MsgID.ExportFileToMaster, params)
for m in msgs:
So your network code first tries to send a list of json encoded data and then tries to send the empty string. It most likely raises an exception because you cannot send a list of anything using sendLine. If you aren't seeing the exception, you've forgotten to enable logging. You should always enable logging so you can see any exceptions that occur.
Also, you're using time.sleep and you shouldn't do this in a Twisted-based program. If you're doing this to try to avoid overloading the receiver, you should use TCP's native backpressure instead by registering a producer which can receive pause and resume notifications. Regardless, time.sleep (and your loop over all the data) will block the entire reactor thread and prevent any progress from being made. The consequence is that most of the data will be buffered locally before being sent.
Also, your code calls LineReceiver.sendLine from a non-reactor thread. This has undefined results but you can probably count on it to not work.
This loop runs in the main thread:
while 1:
time.sleep(0.01)
if connectionToServer == None: continue
if trySend == True:
protocol.ProccessTransmitJobToNode(None, None)
trySend = False
while the reactor runs in another thread:
netThread = threading.Thread(target=reactor.run, kwargs={"installSignalHandlers": False})
netThread.start()
ProcessTransmitJobToNode simply calls self.sendLine:
def ProccessTransmitJobToNode(self, msg, connection):
rootDir = '../documentation/configs/Wooster'
exportedFiles = ['consoleLog.txt', 'blob.dat']
params = {
'Status' : 'buildStatus',
'TaskID' : 'taskID',
'Name' : 'taskName',
'Exports' : len(exportedFiles),
}
msg, statusStr = self._BuildMessage(101, params)
connection.sendLine(msg[0])
You should probably remove the use of threading entirely from the application. Time-based events are better managed using reactor.callLater (your main-thread loop effectively generates a call to ProcessTransmitJobToNode once hundred times a second (modulo effects of the trySend flag)).
You may also want to take a look at https://github.com/twisted/tubes as a better way to manage large amounts of data with Twisted.

Getting error when using value returned by a function as an input for another function

I am a starter in using python. I am showing a section of the code I was working on. I was trying to communicate python to an arduino using pyserial and blinking a LED. I want to use the value returned by the function send_data to be used as an input for function delay_for_goodant. But when I run the code, I get the error
global name data not defined.
Any suggestions to get rid of this?
def openthedoor(set_accepted_list):
if(((len(set_accepted_list)) >0) & (set_forbidden_list == set()):
print"yes,open the gate"
use_door(1)
else:
print"no,close the gate"
use_door(0)
set_for_comparison = set(set_accepted_list & set_list_ant_id)
list_for_comparison = list(set_for_comparison)
return set_for_comparison,list_for_comparison
def establishing_connection():
print ser.read();
ser.write('1')
last_action = -1
def use_door(activate):
global last_action
if(last_action != activate):
send_data(activate)
last_action = activate
def send_data(data):
if (data ==0):
print "manga"
return True
else:
print "muringa"
return False
def delay_for_goodant(data):
print "thenga"
global ser
try:
if (ser == None):
ser = serial.Serial("COM1",9600,timeout = 0)
print "reconnect"
if send_data(data) is True:
ser.write('0')
time.sleep(0)
incoming_data = ser.readline()
print "python is telling arduino to keep the LED dim"
else:
ser.write('1')
time.sleep(0.7)
incoming_data2 = ser.readline()
print "python is telling the arduino to keep the LED bright"
except IOError:
ser = None
I call these functions in later parts of the code as. Am i doing a mistake here? What i am trying to do here is if data ==0, i want to ser.write('1').
establishing_connection()
set_for_comparison,list_for_comparison = openthedoor(set_accepted_list)
activate = use_door()
data = send_data(activate)
arabica = delay_for_goodant(data)
Also the value inside the function delay_for_goodant is not printed.
This is what i get, when i run the code:
True
muringa
Traceback (most recent call last):
File "door_code_final_calib_dig_2.py", line 352, in <module>
arabica = delay_for_goodant(data)
NameError: name 'data' is not defined

Remove new line character from lines in Python

I finally wrote a program to recieve data from a socket:
from socket import *
HOST = 'localhost'
PORT = 30003 #our port from before
ADDR = (HOST,PORT)
BUFSIZE = 4096
sock = socket( AF_INET,SOCK_STREAM)
sock.connect((ADDR))
def readlines(sock, recv_buffer=4096, delim='\n'):
buffer = ''
data = True
while data:
data = sock.recv(recv_buffer)
buffer += data
while buffer.find(delim) != -1:
line, buffer = buffer.split('\n', 1)
yield line
return
for line in readlines(sock):
print line
I am recieving the required data line by line but there is a new line character at the end of each line which is not required for me.
Please tell me how to remove the character at the end of each line. I want to save
these data to a database,line by line, in CSV format.
Regards
Manoj
change
yield line
to
yield line.strip('\n')
if you are running on windows, you might need to do:
yield line.strip('\r\n')