运行Python交互模式与普通模式有哪些不同之处?

5

我有一些Python代码,如果我在Python的交互模式下逐个输入命令,则该代码按预期运行。如果将相同的代码保存为myscript.py并作为'C:\Python27\python.exe myscript.py'运行,则代码会崩溃。

以脚本形式运行Python代码可能导致哪些问题,而同样的代码在交互模式下可以正常工作?

这个问题询问如何判断Python是否处于交互模式。然而,提问者只想要一种可靠的交互模式指纹。我想要列出交互模式和脚本模式的区别,特别关注这可能引起的问题。

例如:

  • sys.path 可能不同
  • os.getcwd() 可能不同
  • os.environ 可能不同
  • 这个问题 的所有答案
  • 这个警告 在 multiprocessing 模块文档开头

Python 的交互模式和脚本模式之间还有哪些不同?


我认为sys或os的问题不会有任何差异,因为两个版本(交互式和脚本)都在相同的上下文中运行。换句话说,无论从哪个给定的目录执行"python script.py"还是"python -i",当前工作目录、路径和环境都是相同的。 - Bryan Oakley
当你说“交互模式”时,你是指运行“python -i”还是通过IDLE运行?这两者之间肯定存在差异。 - Bryan Oakley
好问题,Bryan Oakley。在这个问题中,我正在思考python myscript.pypython -i以及手动键入相同命令之间的区别。如果您对自己的断言(当前工作目录、路径和环境变量将相同)有信心,我会编辑我的问题,删除误导性陈述。 - Andrew
Karl Knechtel,我在想“引发异常”或类似的东西。那是你想知道的定义类型吗?我想我没有考虑到segfault或崩溃Python或BSOD。 - Andrew
有方法可以让CPython崩溃,如果你够邪恶的话,实现方面真的无能为力。但我的意思是:与其试图编译差异列表,为什么不向我们展示导致崩溃的代码以及如何崩溃呢? - Karl Knechtel
啊,卡尔说得非常好。我参考的之前的问题展示了我的一些代码崩溃的情况以及它是如何崩溃的。我非常有兴趣解决这个问题。然而,我也对两种情况如何不同的更一般的问题感兴趣,并且我在谷歌上没有找到好的解释。 - Andrew
3个回答

4

ThreadGreenlet在交互式环境中具有不同的行为。在某些情况下,需要对主事件循环进行修改。

Greenlet来自于Python的一个并发任务模块gevent。它具有与Python(pthread)分开的内部上下文切换机制,并且并发性能非常好(以我的经验)。但是,Greenlet存在某些问题,例如如果未进行猴子补丁(在gevent模块中),则会在阻止C系统调用和套接字交互时进行阻塞。

为了使greenlets正常工作,需要对主事件循环进行修补... 如果您在交互式环境中生成greenlet,它将无法切换上下文并执行。我忘了如何动态修改主事件循环(稍后补充)。

失败的示例:

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()

编辑:

在查看了这个项目的一些代码后,这里是我们如何通过黑客手段使用 gevent 来修改 ipython 输入钩子的方法。

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

修补示例:

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

这听起来是有用的信息。不过我不知道什么是greenlet。如果你能详细解释一下,那可能会让我受益匪浅。 - Andrew
很棒的编辑,更加详细和有用。完全不是我想象中的样子。 - Andrew

2

看起来你正在与硬件进行交互,这就引出了REPL和脚本之间最明显的区别:

在脚本中运行的命令会尽快立即执行,而REPL则等待人类输入。

也就是说,可能存在一个时序问题,硬件可能在执行上一个命令后不会那么快准备好下一个命令。


一个很好的观点。在我提到的硬件特定问题中,我会尝试在每个命令之间添加time.sleep(1)。 - Andrew
好的,我已经尝试在我的硬件相关问题的所有命令之间添加time.sleep(1)。但是结果仍然一样。所以,虽然这个答案很好,但似乎并不能解决另一个问题。 - Andrew

0

看一下这行代码

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

如果您可以使用完整路径来加载LoadLibrary


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接