I have a long script that runs several GPIO devices using both SMBus and pigpio. It starts a thread to cycle through a series of screens on an OLED display, and then connects to Paho MQTT, and keeps track of events with logging for later debugging.
There is a 'master program' called mybox.py
which then uses the much larger script via:
from BIG import Box
box = Box('my box', use_WiFi=True)
box.new_OLEDi2c('my oled')
# box.start_MQTT()
from IDLE:
When I run mybox.py
with IDLE everything works as planned. It spews out messages and then stops with the familliar >>>
I can then type box.start_MQTT()
in IDLE and that will happen. I can continue interacting with the Box
object through IDLE as long as I like.
from Terminal:
When I open a terminal and type python mybox.py
it starts the same way, but then I loose the ability to interact via the terminal. If I type, it is echoed to the screen, but it doesn't go anywhere. Also cursor characters are echoed as ^[[A, ^[[B, ^[[C, ^[[D,
Question: I'm not a developer and I'm learning to swim here by trial and error. Is there some way to get the terminal interaction to work the same easy way as I'm able to do using IDLE?
Is there something about this behavior that sounds familliar? In the past I've been able to use the terminal the way I'd like to without problem, but I wonder if the terminal is being set to a different mode by my script somehow without me knowing about it? For example, I recently found out that typing exit in iTerm returns big red broken pipe banner. Maybe my output is causing the terminal to change state?
GOOD: copy/paste from IDLE:
INFO 2018年12月12日 10:40:52 initiate OLEDi2c("my oled")
OLED initiated in 0.065995 seconds
INFO 2018年12月12日 10:40:52 show_image OLEDi2c("my oled")
showimage opened size w0 h0=(720, 405)
INFO 2018年12月12日 10:40:52 show_image OLEDi2c("my oled")
showimage hscale <= wscale resize size=(113, 64)
INFO 2018年12月12日 10:40:52 show_image OLEDi2c("my oled")
showimage conversion_method "threshold"
Thread me!
keepgoing.isSet(): True
Hey!! keepgoing: <threading._Event object at 0x72d279d0>
dwell_time: None
self.dwell_time: 2
>>>
>>> box.start_MQTT()
trying to connect with MQTT:
pingable is: True
('On Log: ', 'Sending CONNECT (u0, p0, wr0, wq0, wf0, c1, k60) client_id=Luke, I am your client')
connect status: 0
('Disconnect code: ', 0)
loop_start status: ('On Log: ', 'Received CONNACK (0, 0)')
None('Connect code: ', 0)
BAD: copy/paste from Terminal:
INFO 2018年12月12日 10:45:47 initiate OLEDi2c("my oled")
OLED initiated in 0.011983 seconds
INFO 2018年12月12日 10:45:48 show_image OLEDi2c("my oled")
showimage opened size w0 h0=(720, 405)
INFO 2018年12月12日 10:45:48 show_image OLEDi2c("my oled")
showimage hscale <= wscale resize size=(113, 64)
INFO 2018年12月12日 10:45:48 show_image OLEDi2c("my oled")
showimage conversion_method "threshold"
Thread me!
keepgoing.isSet(): True
Hey!! keepgoing: <threading._Event object at 0x73766b70>
dwell_time: None
self.dwell_time: 2
asdf
^[[A^[[A^[[A^[[A^[[A^[[B^[[B^[[B^[[B^[[D^[[C^[[D^[[A('On Log: ', 'Sending PINGREQ')
2 Answers 2
YES! there are ways to get the terminal interaction to work (almost) the same way as in IDLE! Good job at tracking down alternative answers, but I think it's simpler than you might imagine.
There is a >>>
prompt in the terminal if the terminal is running interactive python
.
At the shell command line prompt in the terminal, invoke Python with the -i
(interactive) option, followed by your module filename:
python -i mybox.py
This runs mybox.py
and then presents the >>>
prompt so you can continue to interact with the objects from mybox.py
.
You can use the arrow keys as usual at the >>>
prompt because python
supports command line editing. This is one of the main differences between Idle and Python (in the terminal) because command line editing is implemented with the GNU Readline library in python
and implemented with Python libraries in idle
.
When you want to exit python
in the terminal window, just type control-D at the >>>
prompt, python
will see EOF(end of file) and exit, then you will return to your shell prompt.
-
that's incredible; exactly what I needed. Thank you!uhoh– uhoh2018年12月13日 00:16:45 +00:00Commented Dec 13, 2018 at 0:16
-
A half-year later, I use this every day and it's helped me script much faster. I'm glad you took the time to post.uhoh– uhoh2019年07月06日 05:02:54 +00:00Commented Jul 6, 2019 at 5:02
OK I see. There are two items:
The existence of the thread was keeping things in the terminal from finishing. As soon as I blocked the call to
oled.start_thread()
the master programmybox.py
finished quickly and the$
prompt returned to the screen (python had finished).That provided me with the...
"duh..." moment. Of course there is no
>>>
in the terminal.
That's the explanation.
The answer is: execfile('mybox.py')
temporarily, until I package this more nicely. Per this answer this is not safe, and should instead be handled by an adult (process of some kind). (also see answers to 1, 2, 3)
Problem solved.
update: As pointed out in this comment this is called running in interactive mode and answers to:
-
1The python REPL shell is presumably implemented using readline to implement history and such (so the up and down arrows work, etc) which there will be a python module for.goldilocks– goldilocks2018年12月12日 05:06:14 +00:00Commented Dec 12, 2018 at 5:06
-
@goldilocks yes I see what you mean. That gives me a lot to think about, thanks!uhoh– uhoh2018年12月12日 10:21:01 +00:00Commented Dec 12, 2018 at 10:21
python mybox.py &
note that little&
on the end of the command.box
methods. I am sure I can use your suggestion in the future though, thank you!