rm-hull/luma.led_matrix

Getting 'Too many files open' - what/how to close?

GSVNoFixedabode opened this issue · 5 comments

I'm driving a couple of 8x8 LED MAX7219 displays with a scrolling text (loosley based on matrix_demo.py)

All works ok, but after about 15 minutes the program fails with a 'too many files open' error. I get the text via a requests.get(url) for date/time/temperature then call the output function as per the examples files here, so I assume either requests, serial, or device calls are holding a file/pointer open.

Any idea how to explicitly close these within the main loop? Thanks!
Device: Pi 1B,
OS: Raspbian - Aug 2020
Max open files: 1024

Can you share your code?

After some deep diving in documents I'm wondering if it was the r.requests.get... part so trying r.close after the text extract. I'll leave it to run now and see...

#!/usr/bin/env python3
#coding: UTF-8
import datetime
import requests
import time
import argparse
from luma.led_matrix.device import max7219
from luma.core.interface.serial import spi, noop
from luma.core.legacy import show_message
from luma.core.legacy.font import proportional, CP437_FONT


def output(n, block_orientation, rotate, inreverse, text):
#create matrix device
	serial = spi(port=0, device=0, gpio=noop())
	device = max7219(serial, cascaded=n or 1, block_orientation=block_orientation,
		rotate=rotate or 0, blocks_arranged_in_reverse_order=inreverse)

	show_message(device, text, fill="white", font=proportional(CP437_FONT), scroll_delay=0.05)
	time.sleep(1)

	output(args.cascaded, args.block_orientation, args.rotate, args.reverse_order, args.text)

def generate_text():
	url = "http://10.1.1.111:81/logline.htm"
	try:
		r = requests.get(url)
		logline_text = r.text
		tod = datetime.datetime.now()
	except:
		tod = datetime.datetime.now()
		logline_text = "{} filler -999c ".format(tod.strftime('%H:%M:%S %d-%m-%Y'))

#split the line up separated by whitespace, 4th element is temp, split that to remove the c
	x = logline_text.split()

#catch error if logline corrupt
	try:
		mag = float(x[3].split("c")[0])
	except:
		mag = 999
		print(x)

	weather_text = "{} ".format(tod.strftime('%H:%M:%S %d/%m/%Y')) + str(mag) + "`"
	r.close
	return weather_text

try:
	while(True):
		pulled_text = generate_text()
		output(n=2, block_orientation=90, rotate=0, inreverse=False, text=pulled_text)

except (KeyboardInterrupt, SystemExit):
	print("Stopped")

`

Hmm, that didn't work: lasted 3 hours but ended with the same error

You are repeatedly creating a serial instance and a device instance in the output function. This is likely to be the cause of the error. Try creating the device before the while True line near the bottom and pass it into the output method instead

Also I don’t think you need the following line in the output method

output(args.cascaded, args.block_orientation, args.rotate, args.reverse_order, args.text)

@rm-hull Thanks, that makes sense.

Oh, and that output(args...) like was commented out already but the # dropped when I was formatting the reply above.