In what ways is python different when run in interactive mode?
-
08-06-2021 - |
Question
I have some Python code that works as expected if I type the commands one-at-a-time using Python's interactive mode. The same code crashes if saved as myscript.py
and run as 'C:\Python27\python.exe myscript.py'
.
In what ways could running Python code as a script cause it to crash, if the same code works in interactive mode?
This question asks for ways to tell if python is in interactive mode. However, the asker just wants a single, reliable fingerprint of interactive mode. I'd like a list of ways that interactive mode is different, with particular attention to problems this can cause.
For example:
sys.path
could be differentos.getcwd()
could be differentos.environ
could be different- All the answers to this question
- This warning at the beginning of the multiprocessing module documentation
What else could be different between Python's interactive and script mode?
Solution
It looks like you're interacting with hardware, which brings up the most glaring difference between the REPL and a script:
Commands in a script run immediately as soon as possible, whereas the REPL waits for human input.
That is to say, you are probably having a timing issue where the hardware isn't ready for the next command so soon after executing the previous.
OTHER TIPS
Thread
s and Greenlet
s have different behavior in an interactive environment. The main event loop has to be hacked in some instances.
Greenlet
is from the gevent
module which is a concurrent task in python. It has an internal context switching separate from Python's (pthread) and the concurrency works really well (in my experience). Some of the issues with Greenlets is that they block on blocking C-system calls and socket interactions if they're not monkey-patched (module in gevent
).
The main event-loop needs to be patched in order for the greenlets to work correctly... If you spawn a greenlet in an interactive environment it will not switch contexts and execute, I forgot how off the top of my head how to patch the main event loop (will add later).
Example of failure:
In [1]: from gevent.greenlet import Greenlet
In [2]: def print_hi():
...: print 'hi'
...:
In [3]: print_hi()
hi
In [4]: g = Greenlet(print_hi)
In [5]: g.start()
Edit:
After looking at some of the code on this project here's how we hacked the ipython input hook to use gevent
import sys
import select
import gevent
def stdin_ready():
infds, outfds, erfds = select.select([sys.stdin], [], [], 0)
if infds:
return True
else:
return False
def inputhook_gevent():
try:
while not stdin_ready():
gevent.sleep(0.001)
except KeyboardInterrupt:
pass
return 0
# install the gevent inputhook
from IPython.lib.inputhook import inputhook_manager
inputhook_manager.set_inputhook(inputhook_gevent)
inputhook_manager._current_gui = 'gevent'
# First import the embeddable shell class
from IPython.frontend.terminal.embed import InteractiveShellEmbed
Patched Example:
In [6]: def say_hi():
...: print "hi"
...:
In [7]: g = gevent.greenlet.Greenlet(say_hi)
In [8]: g.start()
In [9]: hi <-- Cursor is here so it printed hi
Take a look at this line
PCO_api = ctypes.oledll.LoadLibrary("SC2_Cam")
If you can use the COMPLETE path for LoadLibrary