程序在BufferedWriter操作期间冻结 - 不可重现

时间:2014-03-17 12:49:52

标签: python python-3.x raspberry-pi bufferedwriter

我使用Python 3.4程序来控制Raspberry Pi的测量设置。该计划的作用如下: - 通过COM端口向微控制器发送命令 - 接收数据包并解析它们 - 将收到的数据和一些统计信息写入文件 - 重复进行下一次测量

整个程序有点像弗兰肯斯坦,因为在我尝试创建之前我对Python一无所知:D所以有很多小的不一致。请不要判断。

#!/usr/bin/python3

import serial
import io
import binascii
import crcmod.predefined
import sys
import struct
import time
import signal
import random
import os
from subprocess import call

REVERSE_BYTE_TABLE = [
        0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
        0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
        0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
        0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
        0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
        0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
        0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
        0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
        0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
        0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
        0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
        0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
        0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
        0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
        0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
        0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
        0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
        0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
        0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
        0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
        0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
        0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
        0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
        0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
        0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
        0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
        0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
        0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
        0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
        0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
        0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
        0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff,
        ]

def reverse_byte(x):

   return REVERSE_BYTE_TABLE[x]

def signal_handler(signal, frame):
   global signalcount
   if(signalcount == 0):
      print("Broke loop")
      signalcount = 1
      raise KeyboardInterrupt()
   elif(signalcount == 1):
      print("\nProgram terminated by user")
      try:
         mean.close()
      except Exception as e:
         print(e)
      sys.exit()

def recovery(cc430):
   call(["gpio", "-g", "write", "24", "1"])
   cc430.flushInput()
   cc430.close()
   cc430.open()
   #cc430.flushOutput()
   cc430.flushInput()
   input = bytearray()
   time.sleep(2)
   call(["gpio", "-g", "write", "24", "0"])
   time.sleep(1)
   cc430.close()
   cc430.open()
   time.sleep(5)
   cc430.write(b'\xd3')
   cc430.write(b'\x01')
   cc430.write(rfset.to_bytes(1, 'big'))
   cc430.write(b'\x00')
   cc430.write(b'\x00')
   cc430.write(b'\x00')
   cc430.write(b'\x30')
   print("Recovery maneuver executed")

   return

rfrange = (14,15,16)
#rfrange = (0,1,2,3,4,5,6,7,8)
#rfrange = (9,10)
rfrange25k = (1,2,3,4)
rfrange10k = (5,6,7,8)
rfrange2k = (9,10,11,12)
rfrangeinfinite = (-1,3,4,7,8,13,14,15,16)

call(["gpio", "export", "24", "out"])

signal.signal(signal.SIGINT, signal_handler)
global signalcount
signalcount = 0
#cc430 = serial.Serial(port='/dev/ttyAMA0', baudrate=115200, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS, timeout=0.05)
#cc430.write(b'\xaa')   #acknowledge proper receiption 0xAA, without, MSP430 will be stuck
#cc430.close()
##sys.exit()
for rfset in rfrange:
   try:
      #rfset = rfset + 1

      cc430 = serial.Serial(port='/dev/ttyAMA0', baudrate=115200, parity=serial.PARITY_NONE, stopbits=serial.STOPBITS_ONE, bytesize=serial.EIGHTBITS, timeout=0.05)
      cc430.close()
      cc430.open()
      input = bytearray()
      beginpaket = bytearray(b"\x4d\xe2\xf8\xe0\x6d\x4e\xb5\x54")
      newline = bytearray(b"\x8a\x8a\x36\x36\x36\x66\xfb\x51")
      crc = 0x0000
      crc2 = 0x0000
      makecrc = crcmod.predefined.mkCrcFun('crc-16-mcrf4xx')
      color = ''
      templist = []
      timelist = []
      timelistint = []
      timelistext = []
      rssilistint = []
      rssilistext = []
      printlist = []
      lastidle = 0
      crcfail = False
      wronginit = False
      dbm = ''
      meter = ''

      with open("dbm", "r+") as f:
         dbm = str(f.readline())[:-1]
         meter = str(f.readline())[:-1]
         measname = str(f.readline())[:-1]
      if(int(dbm) < -81 and (rfset in rfrange25k or rfset == 0)):
         print("dBm kleiner -81, keine messung für rfset " + str(rfset))
         time.sleep(1)
         raise(OSError)
      try:
         os.mkdir("./datasertest/")
      except OSError as err:
         print(err)

      try:
         os.mkdir("./datasertest/" + measname + "/")
      except OSError as err:
         print(err)

      try:
         os.mkdir("./datasertest/" + measname + "/" + meter + "/")
      except OSError as err:
         print(err)

      try:
         os.mkdir("./datasertest/" + measname + "/" + meter + "/" + dbm + "dBm/")
      except OSError as err:
         print(err)

      try:
         os.mkdir("./datasertest/" + measname + "/" + meter + "/" + dbm + "dBm/" + "RF_setting_" + str(rfset).zfill(2) + "/")
      except OSError as err:
         print(err)

      path = measname + "/" + meter + "/" + dbm + "dBm/" + "RF_setting_" + str(rfset).zfill(2) + "/"

      filename = "Reference_Measurement_Signal_Generator_" + meter + "_" + dbm + "dBm_time"
      filename2 = "Reference_Measurement_Signal_Generator_" + meter + "_" + dbm + "dBm_mean"
      avgtime = 0
      laufend = 0
      timestamp1 = time.time()
      timestamp2 = time.time()
      #rfset = 1
      mean = open("./datasertest/" + path + time.strftime('%Y%m%d_%H%M%S_') + filename2 + "_rfsetting_" + str(rfset) + ".log", 'w+')
      run1 = True
      run2 = False
      timestamp1 = time.time()
      rssiOffset = 74
      if(rfset == 0):
         mnumsfortest = 495
      if(rfset in rfrange25k):
         mnumsfortest = 490#200 #was 475
      if(rfset in rfrange10k):
         mnumsfortest = 490#200 #was 490
      if(rfset in rfrange2k):
         mnumsfortest = 498#450 #was 498
      if (rfset in rfrangeinfinite):
         mnumsfortest = -4000
      cyclesfortest = 2502
      cc430.write(b'\xd3')
      cc430.write(b'\x01')
      cc430.write(rfset.to_bytes(1, 'big'))
      cc430.write(b'\x00')
      cc430.write(b'\x00')
      cc430.write(b'\x00')
      cc430.write(b'\x30')

      timebegin = time.time()

      while(cc430.isOpen()):

         if((timestamp1 - time.time()) <= -80 or wronginit):
            if(wronginit):
               print("Wrong initialization")
            else:
               print("Timeout occured")
            recovery(cc430)
            run1 = True
            timestamp1 = time.time()
            input = bytearray()
            wronginit = False
         input.extend(cc430.read(16))

         if newline in input:           #Search for newline
            print("Input Read: " + str(timestamp1 - time.time()))
            timestamp1 = time.time()
            while beginpaket in input:  #As long as there is begin packet in input, but doesn't start at byte 0
               if (beginpaket in input[:8]) and (beginpaket not in input[1:]):    #If begin packet is once in input
                  del input[-8:] # truncate begin and end of packet
                  del input[:8]
                  crc = int.from_bytes([reverse_byte(x) for x in input[-2:]], 'little')
                  print(crc)
                  crc2 = makecrc(input[:-2])
                  #print(crc2)
                  #crc2 = makecrc(input[:-2])
                  #print(crc2)
                  #crc2 = makecrc(input[:int(len(input)/2)])
                  #crc2 = makecrc(input[int(len(input)/2):-2], crc2)
                  #print(crc2)

                  if not (crc == crc2): #CRC OK?
                     print("CRC Fail")  #inform user anyhow
                     recovery(cc430)
                     run1 = True
                     crcfail = True
                     break
                  cc430.write(b'\xaa')  #acknowledge proper receiption 0xAA, without, MSP430 will be stuck
                  del input[-2:]        #remove CRC from end of packet
                  break
               else:
                  del input[0]      #Delete byte zero, because not part of begin paket


            if not(crcfail):

               while len(input) > 0:        #Keep parsing while there is packet left
                  if input[0] == 0x00:   #MNUM
                     print("Measurement number %d" % int.from_bytes(input[1:3], 'big'))
         #            print(int.from_bytes(input[1:3], 'big'))
                     del input[0:3]
                     if len(input) == 0:
                        break
                  if input[0] == 0x01:   #CLK_INT
         #            print(int.from_bytes(input[1:3], 'big'))
                     tmpClkInt = int.from_bytes(input[1:5], 'big')
                     timelistint.append(tmpClkInt)
                     del input[0:5]
                     if len(input) == 0:
                        break
                  if input[0] == 0x02:   #CLK_EXT
         #            print(int.from_bytes(input[1:3], 'big'))
                     tmpClkExt = int.from_bytes(input[1:5], 'big')
                     timelistext.append(tmpClkExt)
                     del input[0:5]
                     if len(input) == 0:
                        break
                  if input[0] == 0x03:   #RSSI_INT
         #            print("Last RSSI value: %d" % int.from_bytes(input[1:2], 'big'))
         #            print(int.from_bytes(input[1:2], 'big'))
                     tmpRSSIint = int.from_bytes(input[1:2], 'big')
                     if(tmpRSSIint >= 128):
                        tmpRSSIint = ((tmpRSSIint - 256) / 2) - rssiOffset
                     else:
                        tmpRSSIint = (tmpRSSIint / 2) - rssiOffset
                     rssilistint.append(tmpRSSIint)
                     del input[0:2]
                     if len(input) == 0:
                        break
                  if input[0] == 0x04:   #RSSI_EXT
         #            print(int.from_bytes(input[1:2], 'big'))
                     tmpRSSIext = int.from_bytes(input[1:2], 'big')
                     if(tmpRSSIext >= 128):
                        tmpRSSIext = ((tmpRSSIext - 256) / 2) - rssiOffset
                     else:
                        tmpRSSIext = (tmpRSSIext / 2) - rssiOffset
                     rssilistext.append(tmpRSSIext)
                     del input[0:2]
                     if len(input) == 0:
                        break
                  if input[0] == 0x05:   #TEMP_INT
                     print(int.from_bytes(input[1:3], 'big'))
                     templist.append(int.from_bytes(input[1:3], 'big'))
                     del input[0:3]
                     if len(input) == 0:
                        break
                  if input[0] == 0x06:   #TEMP_EXT
                     print(int.from_bytes(input[1:3], 'big'))
                     del input[0:3]
                     if len(input) == 0:
                        break
                  if input[0] == 0x07:   #AVG_CLK_INT
                     print(int.from_bytes(input[1:5], 'big'))
                     del input[0:5]
                     if len(input) == 0:
                        break
                  if input[0] == 0x08:   #AVG_CLK_EXT
                     print(struct.unpack_from("f", input[1:5]))
                     print(':'.join(hex(x) for x in input[1:5]))
                     print(':'.join(bin(x) for x in input[1:5]))
                     del input[0:5]
                     if len(input) == 0:
                        break
                  if input[0] == 0x09:
                     print(input[2:(input[1] + 1)].decode('cp1252')) #decode String with Windows encoding
                     if input[2] == 0x00:
                        color = 'error'
                     if input[2] == 0x01:
                        color = 'warning'
                     if input[2] == 0x02:
                        color = 'data'
                     if input[2] == 0x03:
                        color = 'success'
                     if input[2] == 0x04:
                        color = 'boring'
                     del input[0:(input[1] + 2)]
                     if len(input) == 0: #leave parser @ end of packet
                        break
                  if input[0] == 0x0A:   #PI_RFSTATUS
                     #print(int.from_bytes(input[1:2], 'big'))
                     #print(':'.join(bin(x) for x in input[1:2]))
                     print(':'.join(hex(x) for x in input[1:2]))
                     del input[0:2]
                     if len(input) == 0:
                        break
                  if input[0] == 0x0B:   #PKT_LOSS
         #            print("Number of lost packeges in last measurement: %d" % int.from_bytes(input[1:3], 'big'))
         #            print(int.from_bytes(input[1:3], 'big'))
                     del input[0:3]
                     if len(input) == 0:
                        break
                  if input[0] == 0x0C:   #CRC_ERR
         #            print("Number of CRC errors in last measurement: %d" % int.from_bytes(input[1:3], 'big'))
         #            print(int.from_bytes(input[1:3], 'big'))
                     del input[0:3]
                     if len(input) == 0:
                        break
                  if input[0] == 0x0D:   #IDLE_COUNT
                     thisidle = int.from_bytes(input[1:5], 'big')
         #            print("Idle Count: %d calculated from this idle %d and lastidle %d" % (thisidle - lastidle, thisidle, lastidle))
         #            print(int.from_bytes(input[1:5], 'big'))
                     lastidle = thisidle
                     del input[0:5]
                     if len(input) == 0:
                        break
                  if input[0] > 0x0D:
                     print(str(input[0]) + " is invalid packet identifier: break parsing")
                     break


               input = bytearray()
               avgtemp = 0
               for i in range(len(templist)):
                  avgtemp += templist[i]
               if len(templist) > 0:
                  lol = 1
         #         print(avgtemp/len(templist))
         #      random.seed(avgtime)
               avgtime = 0
         #      randomlist = list(timelistext)
         #      random.shuffle(randomlist, random.random)
         #      print(randomlist)
               for i in range(len(timelistint)):
                  if (i == 0):
                     offset = -1
                  else:
                     offset = i - 1
                  timelist.append(timelistint[i]-timelistext[i])
                  printlist.append(str(timelistint[i]-timelistext[i]) + ";" + str(timelistint[i]) + ";" + str(timelistext[i]) + ";" + str(rssilistint[i]) + ";" + str(rssilistext[i]))# + ";" + str(timelistext[offset]) + ";" + str(randomlist[i]))
         #      for i in timelist:
         #         print(i)
               print("Länge Timelist: " + str(len(timelist)))
               timelistdel = []
               for i in range(len(timelist)):
                  if (timelistint[i] == 0 or timelistext[i] == 0):
          #           print("Timelist item bigger then 1000 or <= 0, Abort, Abort:   %d  No: %d" % (timelist[i], i))
                     timelistdel.append(i)
                  else:
                     avgtime += timelist[i]
               for i in timelistdel[::-1]:
                  del timelist[i]
         #         del printlist[i]
               print("Länge Timelist: " + str(len(timelist)))
               print("Länge Printlist: " + str(len(printlist)))
               print("Messung " + str(laufend) + " von rfset " + str(rfset))
               if not (len(printlist) == 0):
                  with open("./datasertest/" + path + time.strftime('%Y%m%d_%H%M%S_') + filename + '_' + str(laufend) + '_rfsetting_' + str(rfset) + ".log", 'w+') as f:
                     for string in printlist:
                        f.write(str(string) + '\r\n')
         #               print(i)
                  laufend = laufend + 1
               avgmean = 0
               if len(timelist) > 0:
                  lol = 2
                  avgmean = avgtime/len(timelist)
                  print(avgmean)
                  mean.write(str(avgmean) + '\r\n')
               if not (run1 or run2):
                  if((avgmean > 600 and avgmean < 640) or (avgmean > 2800 and avgmean < 3200)):
                     wronginit = True
               timelist = []
               timelistint = []
               timelistext = []
               rssilistint = []
               rssilistext = []
               printlist = []
               mnumsfortest += 1
         #      mnumsfortest = 27
               if (mnumsfortest > 500):
                  mean.close()
                  print("\nFertig\n")
                  break
               time.sleep(3)
               if(run2):
                  run2 = False
               if(run1):
                  print("Run 1 - Sleep 20 s")
                  run1 = False
                  run2 = True
                  time.sleep(20)
               cc430.write(b'\xd3')
               cc430.write(b'\x01')
         #      cc430.write(b'\x07')
               cc430.write(rfset.to_bytes(1, 'big'))
         #      cc430.write(int(mnumsfortest/3).to_bytes(1, 'big'))
               #for by in mnumsfortest.to_bytes(2, 'big'):
               #   cc430.write(y)
               absmnumsfortest = abs(mnumsfortest)
               cc430.write(absmnumsfortest.to_bytes(2, 'big'))
         #      cyclesfortest = 1000
               #for by in cyclesfortest.to_bytes(2, 'big'):
               #   cc430.write(by)
               cc430.write(cyclesfortest.to_bytes(2, 'big'))
            else:
               crcfail = False
            if(time.time() - timebegin > 54000):
               print("Time up! Next RF-Set")
               break
            if(time.time() - timebegin > 38160 and rfset == 14):
               print("Time up for RF 14! Next RF-Set")
               break
   except KeyboardInterrupt as keyi:
      print("Loop: " + str(rfset) + " interrupted")
      time.sleep(1) #Delay to hit CTRL + C two times
      signalcount = 0
   except OSError as oeri:
      print(oeri)
      pass   

现在的问题是,虽然程序大部分时间都运行良好(连续几个小时到几天)但它有时会停止。程序中出现的位置每次都不同,但似乎总是在BufferedWriter操作期间发生。当我看到程序没有执行更多测量时,我按Ctrl + C退出。我收到以下三条错误消息:

Messung 1901 von rfset 3
-282499.4179164167
^C^CBroke loop
Traceback (most recent call last):
  File "./autosertest.py", line 177, in <module>
    input.extend(cc430.read(16))
  File "/usr/lib/python3/dist-packages/serial/serialposix.py", line 442, in read
    ready,_,_ = select.select([self.fd],[],[], self._timeout)
  File "./autosertest.py", line 57, in signal_handler
    print("Broke loop")
  File "./autosertest.py", line 57, in signal_handler
    print("Broke loop")
RuntimeError: reentrant call inside <_io.BufferedWriter name='<stdout>'>
--
Messung 364 von rfset 3
615.0213957208558
Input Read: -29.404370069503784
39232
Länge Timelist: 5002
Länge Timelist: 5000
Länge Printlist: 5002^C
Traceback (most recent call last):
  File "./autosertest.py", line 396, in <module>
    print("Länge Printlist: " + str(len(printlist)))
  File "./autosertest.py", line 57, in signal_handler
    print("Broke loop")
RuntimeError: reentrant call inside <_io.BufferedWriter name='<stdout>'>
--
1
Länge Timelist: 2500
Länge Printlist: 2502
Messung 640 von rfset 14
517.8528
^CInput Read: -15.271323919296265
Traceback (most recent call last):
  File "./autosertest.py", line 220, in <module>
    print("Input Read: " + str(timestamp1 - time.time()))
  File "./autosertest.py", line 57, in signal_handler
    print("Broke loop")
RuntimeError: reentrant call inside <_io.BufferedWriter name='<stdout>'>

我知道,可重入调用来自信号处理程序,它试图写入已经在使用的资源(stdout),并且应该避免在信号处理程序中执行I / O.但我认为,这不是问题,而是程序不会从写操作返回。

您可能想知道的参数:

  • python版本:Python 3.4.0b2
  • linux版本:Linux raspberrypi 3.6.11+#371预览2月7日星期四16:31:35 GMT 2013 armv6l GNU / Linux

0 个答案:

没有答案