5

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 different
  • os.getcwd() could be different
  • os.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?

6
  • I don't think the issues with sys or os would ever be different, given that both versions (interative versus script) are run in the same context. In other words, from any given directory if you do "python script.py" or "python -i", the cwd, path and environment will be identical. Commented May 11, 2012 at 20:20
  • when you say "in iteractive mode" are you talking about running "python -i", or are you talking about running via IDLE? There are definitely some differences between those two. Commented May 11, 2012 at 20:25
  • Good question, Bryan Oakley. In this question, I was thinking of python myscript.py versus python -i and typing the same commands manually. If you're confident about your assertions (cwd, path and envronment will be identical), I'll edit my question to remove my misleading statements. Commented May 11, 2012 at 20:31
  • Karl Knechtel, I was thinking of 'raises an exception', or something similar. Is that the type of definition you were wondering about? I guess I wasn't thinking of a segfault or crashing out of python or BSOD. Commented May 11, 2012 at 21:05
  • There are ways to make CPython crash, if you're sufficiently evil, that the implementation can't really do anything about. But what I'm getting at: instead of trying to compile a list of differences, why not show us the code that's crashing and how it's crashing? Commented May 11, 2012 at 21:20

3 Answers 3

4

Threads and Greenlets 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
Sign up to request clarification or add additional context in comments.

2 Comments

This sounds like good information. I don't know what a greenlet is, though. If you elaborate, it would probably educate me.
Great edit, much more informative. Certainly not anything I suspected.
2

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.

2 Comments

An excellent point. In the hardware-specific question I reference, I'll try adding time.sleep(1) in between every command.
Ok, I tried adding time.sleep(1) between all the commands in my hardware-related question. The behavior is the same. So, great answer to this question, doesn't seem to solve the other one.
0

Take a look at this line

PCO_api = ctypes.oledll.LoadLibrary("SC2_Cam")

If you can use the COMPLETE path for LoadLibrary

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.