rebthetractorman
Posts: 2
Joined: Tue Dec 03, 2019 6:18 pm

Loop () Code Structure

Sat Dec 07, 2019 2:03 pm

I am needing a little help with coding a loop function into my python program!
basically what I have a python file called "main.py"
in this file I am able to call sub python files, by using the exec() command.
this is all working great!
however, now I have a sub file that I need to be able to run endlessly until a key is pressed on the keyboard. (input())
Nothing I seem to be doing is working in a typical loop type fashion.
basically while in the loop I need it to do two main things:

exec (open("subfile.py").read())
input()

that's it!
anybody have any code tips?
Thank You!

User avatar
paddyg
Posts: 2522
Joined: Sat Jan 28, 2012 11:57 am
Location: UK

Re: Loop () Code Structure

Sun Dec 08, 2019 7:20 pm

Is there a reason you need to run your subfiles in that rather non-standard way? Normally you would import the subfile once at the start of main and have a function with a loop in subfile that would check for input and stop accordingly. Maybe if you give some more info about what you're trying to do you might get some suggestions of ways to do it. (You can start other programs in subprocesses which you can 'kill' but it's generally not a good design. Using exec() is generally also suspect.)
also https://groups.google.com/forum/?hl=en-GB&fromgroups=#!forum/pi3d

rebthetractorman
Posts: 2
Joined: Tue Dec 03, 2019 6:18 pm

Re: Loop () Code Structure

Tue Dec 10, 2019 3:49 pm

Sorry for the delay in response.
I have figured out what I was doing wrong, and now have a fully functional script.
Here is what I ended up doing.

Code: Select all

# // Pellet Drop Routine
print("Step 6: Pellet Distrabution System")
print("    Pellets will now be dispensed.")
while True:
    try:
        exec (open("pel_drop_med.py").read())
    except:
        print("pelfeed has ended!")
        break
Basically In a nut shell here is what I have done. My PCB went out in my Whittfield Pellet stove. It would cost me about $350.00 to replace the obsolete Board, so For about $130.00 I built my own system using the RaspberryPi, an 8 Channel 5V Relay Board, a couple Dimmer boards, etc. This controls the two motors, the auger, the three temperature sensors and the igniter. I'm using python as the back end System.

I will be updating the system a little more, as I am thinking about replacing the existing igniter element which takes about 8-10 minutes to get hot enough to ignite, with a propane igniter (hooked to a 1 Lb Bottle at the back of stove, hidden from sight. This takes about 3 seconds to ignite... Big difference! I am also replacing the OEM temperature sensors, which are snap style, with probe style sensors.

I will eventually build a Web gui for this!
Would be a fun project to get others involved with.

User avatar
paddyg
Posts: 2522
Joined: Sat Jan 28, 2012 11:57 am
Location: UK

Re: Loop () Code Structure

Tue Dec 10, 2019 9:56 pm

@rebthetractorma, well done for getting it working. It sounds a really interesting project and it would be good to share your ideas with others in the same position. I definitely don't want to pour cold water on your enthusiasm but the system does need to be fail-safe. i.e. if it goes wrong the result is a stove going out or not lighting as opposed to the stove getting hotter and hotter until it sets the building on fire - or fills the area with propane before lighting it. Sharing your code with other users is helpful in this respect as more people looking at it increases the chance of spotting bugs.

The other thing you need to think about if you add a web interface is that your raspberry pi might get hacked (IOT hacking is now a major issue) and stop behaving the way you expect, or even get your software tweaked to cause damage. That is why the use of exec() is frowned upon as it provides a route for an external party to run code if they can get a file with the right name in the right location. I know it sounds far-fetched, after all if someone has managed to upload a file into the relevant directory they probably already have serious access, but why add additional risks?

A more conventional way to do what you look to be trying would be to have pel_drop_med.py looking like

Code: Select all

import gpiozero
# other setup stuff

def do_feed():
    if sensor.value > THRESHOLD:
        motor.on()
        time.sleep(10.0)
        motor.off()
    if sensor.value > THRESHOLD:
        return True
    return False
then in your main file

Code: Select all

import pel_drop_med #NB you don't put the py on the end
...
# // Pellet Drop Routine
print("Step 6: Pellet Distrabution System")
print("    Pellets will now be dispensed.")
while pel_drop_med.do_feed()
    time.sleep(0.01)
Obviously I've no idea what happens in pel_drop_med but the idea is that you put the stuff you want to happen repeatedly into a function. The one-off setup just needs to happen once. Also there needs to be other checks to make sure it doesn't keep running if the sensor's broken etc etc.

An additional thing to have in mind is avoiding duplication of code at almost any cost. It's very easy to copy paste code then tweak a few bits but this is generally the root cause of bugs and debugging problems. The name pel_drop_med might indicate that there is also a pel_drop_low and pel_drop_high (quite possibly jumping to conclusions) but it would be much more maintainable code to have one function and pass it a variable, i.e. in my made up example

Code: Select all

 do_feed(tm=10.0):
       ...
       time.sleep(tm)
also https://groups.google.com/forum/?hl=en-GB&fromgroups=#!forum/pi3d

Return to “Python”