zitman
Posts: 20
Joined: Wed Jul 18, 2012 11:02 am

Running a never ending loop Python script at startup

Fri Nov 09, 2012 8:40 pm

Hi all,

I have created a Python script which interfaces with I2C devices (RTC, 4 x 20 LCD Display, 2 Temperature sensors) and displays a bunch of info on the LCD. I do this using an endless loop in the Python code using:

while (1 == 1)

I have added this to the /etc/init.d and it runs fine. The only issue I have is that when I boot the Pi it stops at or shortly after init.d runs the script. I can still log in via SSH (which is my normal route) but would like it to work correctly without "hanging" the boot process.

I am new to Python and am open to any and all comments or help.

Thanks

Z

rickseiden
Posts: 411
Joined: Thu Aug 02, 2012 12:21 pm
Location: Buffalo, NY, USA

Re: Running a never ending loop Python script at startup

Fri Nov 09, 2012 9:02 pm

Try adding an & to the end of it. That tells the system to run it in the background.

sudo python someApp.py &

Just guessing, but that might work.


Rick
There are 10 types of people in this world. Those that understand binary, and those that don't.

BlackJack
Posts: 288
Joined: Sat Aug 04, 2012 8:28 am
Contact: Website

Re: Running a never ending loop Python script at startup

Fri Nov 09, 2012 10:14 pm

@zitman: The parenthesis around the condition are unnecessary and the result of ``1 == 1`` is `True`, so ``while True:`` is shorter and a more direct expression.

Code: Select all

while not self.asleep():
    sheep += 1

zitman
Posts: 20
Joined: Wed Jul 18, 2012 11:02 am

Re: Running a never ending loop Python script at startup

Fri Nov 09, 2012 11:55 pm

@RickSeiden - That worked perfectly. Thanks. The last time I used Unix in anger was the late eighties and it's funny the things you forget (and the things you remember!). As soon as I read your reply I thought 'I knew that'. I always thought back then that Unix was a great operating system and Linux on the Pi is bringing back a lot of memories.

@BlackJack - The brackets is a personal thing for me, I hate code with while, if, do clauses that don't have brackets but as I say its a personal thing (I drive everyone at work nuts because I keep uppercasing all the key words in SQL statements). As for the while true, I thought I had tried that and it hadn't worked but checking my code I had used true in lower case! So another thing learned.

Again thanks both.

Z

Boezelman
Posts: 40
Joined: Sun Aug 05, 2012 3:25 pm

Re: Running a never ending loop Python script at startup

Sun Nov 11, 2012 3:21 pm

Could you share your code please?! :D

zitman
Posts: 20
Joined: Wed Jul 18, 2012 11:02 am

Re: Running a never ending loop Python script at startup

Sun Nov 11, 2012 7:17 pm

Certainly. There are two code files as I have extracted all of the LCD handling to a separate file:

Main Code:

Code: Select all

#! /usr/bin/python

import smbus
import sys
import time
import socket
import i2c_LCD

bus = smbus.SMBus(0)
ErrorCount = 0;

i2c_LCD.Setup(bus, 4, 20);
time.sleep(0.5);
i2c_LCD.Clear(bus);
time.sleep(0.5);

Socket_IPAddress = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
Socket_IPAddress.connect(("google.com", 80))
IPAddress = Socket_IPAddress.getsockname()[0]
Socket_IPAddress.close();

bus = smbus.SMBus(0)

i2c_LCD.PrintAt(bus, 1, 1, "RPi:");
i2c_LCD.PrintAt(bus, 1, 6, IPAddress);

while (1 == 1):
	try:

		register_day = bus.read_byte_data(0x68, 0x04);
		register_month = bus.read_byte_data(0x68, 0x05);
		register_year = bus.read_byte_data(0x68, 0x06);

		register_hours = bus.read_byte_data(0x68, 0x02);
		register_minutes = bus.read_byte_data(0x68, 0x01);
		register_seconds = bus.read_byte_data(0x68, 0x00);


		day = (register_day & 0xF) + (((register_day & 0xF0) >> 4) * 10);
		month = (register_month & 0xF) + (((register_month & 0xF0) >> 4) * 10);
		year = (register_year & 0xF) + (((register_year & 0xF0) >> 4) * 10);

		hours = (register_hours & 0xF) + (((register_hours & 0XF0) >> 4) * 10);
		minutes = (register_minutes & 0xF) + (((register_minutes & 0xF0) >> 4) * 10);
		seconds = (register_seconds & 0xF) + (((register_seconds & 0XF0) >> 4) * 10);

		temperature1 = bus.read_byte_data(0x48, 0x00);
		temperature2 = bus.read_byte_data(0x49, 0x00);

	except:
		ErrorCount += 1;
		print "Error ocurred (Count: {0})".format(ErrorCount);
		time.sleep(1);

	i2c_LCD.PrintAt(bus, 3, 1, '{0:02d}/{1:02d}/20{2:02d}'.format(day, month, year));
	i2c_LCD.PrintAt(bus, 3, 15, '{0} C'.format(temperature1));
	time.sleep(0.5);

	i2c_LCD.PrintAt(bus, 4, 1, '{0:02d}:{1:02d}:{2:02d}'.format(hours, minutes, seconds));
	i2c_LCD.PrintAt(bus, 4, 15, '{0} C'.format(temperature2));
	time.sleep(0.5);
LCD Code:

Code: Select all

#! /usr/bin/python

import time

i2cDeviceID_LCD = 0x31;

def Setup(i2cBus, Rows, Columns):
	i2cBus.write_byte(i2cDeviceID_LCD, 0x1b);
	i2cBus.write_byte(i2cDeviceID_LCD, 0x30);
	i2cBus.write_byte(i2cDeviceID_LCD, Rows);
	time.sleep(0.1);
	i2cBus.write_byte(i2cDeviceID_LCD, 0x1b);
	i2cBus.write_byte(i2cDeviceID_LCD, 0x31);
	i2cBus.write_byte(i2cDeviceID_LCD, Columns);
	time.sleep(0.1);


def Clear(i2cBus):
	i2cBus.write_byte(i2cDeviceID_LCD, 0x1b);
	i2cBus.write_byte(i2cDeviceID_LCD, 0x50);
	time.sleep(0.01);

def Print(i2cBus, StringToPrint):
	for Char in StringToPrint:
		i2cBus.write_byte(i2cDeviceID_LCD, ord(Char));
	time.sleep(0.01);

def PrintAt(i2cBus, Row, Column, StringToPrint):
	i2cBus.write_byte(i2cDeviceID_LCD, 0x1b);
	i2cBus.write_byte(i2cDeviceID_LCD, 0x24);
	i2cBus.write_byte(i2cDeviceID_LCD, Row);
	i2cBus.write_byte(i2cDeviceID_LCD, Column);
	Print(i2cBus, StringToPrint);
Please note I am still finding my feet in Python!! :)

Z

BlackJack
Posts: 288
Joined: Sat Aug 04, 2012 8:28 am
Contact: Website

Re: Running a never ending loop Python script at startup

Sun Nov 11, 2012 8:41 pm

@zitman: I guess all those unnecessary semicolons are also a personal thing for you‽ ;-)

Writing a function for the BCD conversion makes the code a bit shorter/cleaner.

A bare ``except`` without any specific exceptions isn't a good idea. You are reducing every possible exception to a message how many errors have occured so far. This may include `MemoryError`, or `NameError` if there is a spelling mistake somewhere in the ``try`` block. Even attempts to stop the program with CTRL+C will have no effect but increasing the error count if the event occurs while the control flow is within the ``try`` block. At least handle `Exception` (which does not include the CTRL-C exception), assign the exception to a name and print it alongside the error count.

Untested:

Code: Select all

#!/usr/bin/env python
# coding: utf-8
import contextlib
import time
import socket
import smbus
import i2c_LCD


def from_bcd(number):
    high_nibble, low_nibble = divmod(number, 16)
    if not all(0 <= nibble <= 9 for nibble in [high_nibble, low_nibble]):
        raise ValueError('%02x is not a valid BCD byte value' % number)
    return high_nibble * 10 + low_nibble


def main():
    bus = smbus.SMBus(0)

    i2c_LCD.Setup(bus, 4, 20)
    time.sleep(0.5)
    i2c_LCD.Clear(bus)
    time.sleep(0.5)

    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    with contextlib.closing(sock.connect(('google.com', 80))):
        ip_address = sock.getsockname()[0]

    # bus = smbus.SMBus(0)  # Again‽

    i2c_LCD.PrintAt(bus, 1, 1, 'RPi:')
    i2c_LCD.PrintAt(bus, 1, 6, ip_address)
    
    error_count = 0
    while True:
        try:
            day, month, year = (
                from_bcd(bus.read_byte_data(0x68, i)) for i in xrange(4, 7)
            )
            hours, minutes, seconds = (
                from_bcd(bus.read_byte_data(0x68, i))
                for i in reversed(xrange(0, 3))
            )
            temperature1 = bus.read_byte_data(0x48, 0)
            temperature2 = bus.read_byte_data(0x49, 0)
        except Exception as error:
            error_count += 1
            print 'Error ocurred (Count: {0}): {1}'.format(error_count, error)
            time.sleep(1)

        i2c_LCD.PrintAt(
            bus, 3, 1, '{0:02d}/{1:02d}/20{2:02d}'.format(day, month, year)
        )
        i2c_LCD.PrintAt(bus, 3, 15, '{0} C'.format(temperature1))
        time.sleep(0.5)

        i2c_LCD.PrintAt(
            bus, 4, 1, '{0:02d}:{1:02d}:{2:02d}'.format(hours, minutes, seconds)
        )
        i2c_LCD.PrintAt(bus, 4, 15, '{0} C'.format(temperature2))
        time.sleep(0.5)


if __name__ == '__main__':
    main()

Code: Select all

while not self.asleep():
    sheep += 1

zitman
Posts: 20
Joined: Wed Jul 18, 2012 11:02 am

Re: Running a never ending loop Python script at startup

Tue Nov 13, 2012 1:47 pm

@BlackJack: :D No the semicolons are more of an incompetence thing! I was convinced I needed them, must have been programming in C or SQL too much.

All the other comments are duly noted and acted upon.

Cheers

Z

davadvice
Posts: 13
Joined: Thu Oct 18, 2012 7:21 pm

Re: Running a never ending loop Python script at startup

Sat Nov 17, 2012 9:02 am

Hi zitman,

what temperature sensors are you using for this application?

I have a set up using the GPIO and a DS18B20.

thanks
David

buxiaoyang
Posts: 21
Joined: Wed Dec 05, 2012 1:25 pm

Re: Running a never ending loop Python script at startup

Wed Dec 05, 2012 1:34 pm

Thanks very much for your post! actually i encounter the same problem. Could you kindly share me how did you add the script to the /etc/init.d? I can now run my script by type python /projects/lcd12864/v6/main.py
/projects/lcd12864/v6/main.py is my script path.

Thanks in advance!

canibalimao
Posts: 557
Joined: Tue Aug 07, 2012 8:48 pm
Location: Portugal

Re: Running a never ending loop Python script at startup

Tue Dec 18, 2012 12:33 pm

buxiaoyang wrote:Thanks very much for your post! actually i encounter the same problem. Could you kindly share me how did you add the script to the /etc/init.d? I can now run my script by type python /projects/lcd12864/v6/main.py
/projects/lcd12864/v6/main.py is my script path.

Thanks in advance!
I have the same problem as you. I want to have my LCD's python script to run on background at startup and I don't know how :(

User avatar
RaTTuS
Posts: 9895
Joined: Tue Nov 29, 2011 11:12 am
Location: North West UK

Re: Running a never ending loop Python script at startup

Tue Dec 18, 2012 12:43 pm

if you start your script with
/path/to/script/script.py
then
/path/to/script/script.py &
will make it run in the background
How To ask Questions :- http://www.catb.org/esr/faqs/smart-questions.html
WARNING - some parts of this post may be erroneous YMMV

1QC43qbL5FySu2Pi51vGqKqxy3UiJgukSX
Covfefe

canibalimao
Posts: 557
Joined: Tue Aug 07, 2012 8:48 pm
Location: Portugal

Re: Running a never ending loop Python script at startup

Tue Dec 18, 2012 1:44 pm

I have it running on backgroud now, but how do I put it running on startup?

-rst-
Posts: 1316
Joined: Thu Nov 01, 2012 12:12 pm
Location: Dublin, Ireland

Re: Running a never ending loop Python script at startup

Tue Dec 18, 2012 2:02 pm

canibalimao wrote:I have it running on backgroud now, but how do I put it running on startup?
Maybe this helps: http://www.ghacks.net/2009/04/04/get-to ... directory/
http://raspberrycompote.blogspot.com/ - Low-level graphics and 'Coding Gold Dust'

canibalimao
Posts: 557
Joined: Tue Aug 07, 2012 8:48 pm
Location: Portugal

Re: Running a never ending loop Python script at startup

Tue Dec 18, 2012 3:24 pm

Thank you very much -rst- . I think that this is really what I want :D

020110348
Posts: 18
Joined: Thu Mar 21, 2013 12:07 pm

Re: Running a never ending loop Python script at startup

Fri Mar 22, 2013 12:04 pm

Continuing with Run at startup + In background.

I have a button on GPIO that i want to beable to hit a virtual excape key. I put command to launch it in rc.local "sudo python /home/pi/run.py &" (now typing this out i think my mistake is expicitly calling python, do i need to call python?) and normaly it wouldnt boot past this code, just stop booting and take button presses.
every time i put it with the "&" it just returns a random number, why is that?

Im not with my computer now, sorry for lack of information.

-rst-
Posts: 1316
Joined: Thu Nov 01, 2012 12:12 pm
Location: Dublin, Ireland

Re: Running a never ending loop Python script at startup

Fri Mar 22, 2013 12:43 pm

The ampersand ('&') at the end of a command means 'run this in the background and don't wait for it to exit' - so if you leave it out, your startup script gets stuck waiting for the python script to exit. With the ampersand on the line, the 'random number' output is the process id of the background process - output in case you would want to use it to control the process.

You don't necessarily need to use 'sudo python yourscript.py' - you can make your script executable using 'chmod a+x yourscript.py' (or thereabouts) - so then the command in rc.local would be "sudo /home/pi/run.py &"
http://raspberrycompote.blogspot.com/ - Low-level graphics and 'Coding Gold Dust'

canibalimao
Posts: 557
Joined: Tue Aug 07, 2012 8:48 pm
Location: Portugal

Re: Running a never ending loop Python script at startup

Fri Mar 22, 2013 1:39 pm

020110348 wrote:Continuing with Run at startup + In background.

I have a button on GPIO that i want to beable to hit a virtual excape key. I put command to launch it in rc.local "sudo python /home/pi/run.py &" (now typing this out i think my mistake is expicitly calling python, do i need to call python?) and normaly it wouldnt boot past this code, just stop booting and take button presses.
every time i put it with the "&" it just returns a random number, why is that?

Im not with my computer now, sorry for lack of information.
That random number is the process number. If you want to "kill" the process you need to send the comand "sudo kill ******" where "*****" is that random number.

020110348
Posts: 18
Joined: Thu Mar 21, 2013 12:07 pm

Re: Running a never ending loop Python script at startup

Fri Mar 22, 2013 2:58 pm

thank you... will add apersand, can i store that prcessed id number? somewere, or will it be the same every time?

-rst-
Posts: 1316
Joined: Thu Nov 01, 2012 12:12 pm
Location: Dublin, Ireland

Re: Running a never ending loop Python script at startup

Fri Mar 22, 2013 3:07 pm

It will not be the same every time. You could store the pid into a variable in your shell script and save it into a file - something along:

Code: Select all

sudo yourscript & PID=$!
echo $PID >yourscript.pid
http://raspberrycompote.blogspot.com/ - Low-level graphics and 'Coding Gold Dust'

Return to “Python”

Who is online

Users browsing this forum: No registered users and 18 guests