【问题标题】:In what ways is python different when run in interactive mode?python 在交互模式下运行时有何不同?
【发布时间】:2012-05-20 10:34:51
【问题描述】:

如果我使用 Python 的交互模式一次键入一个命令,我的 some Python code 会按预期工作。如果保存为myscript.py 并以'C:\Python27\python.exe myscript.py' 运行,相同的代码会崩溃。

如果相同的代码在交互模式下运行,将 Python 代码作为脚本运行会以何种方式导致其崩溃?

This question 询问判断 python 是否处于交互模式的方法。然而,提问者只想要一个单一的、可靠的交互模式指纹。我想要一个交互模式不同方式的列表,特别注意这可能导致的问题。

例如:

  • sys.path 可能不同
  • os.getcwd() 可能不同
  • os.environ 可能不同
  • this question的所有答案
  • This warning 多处理模块文档开头

Python 的交互模式和脚本模式还有什么不同?

【问题讨论】:

  • 我不认为 sys 或 os 的问题会有所不同,因为这两个版本(交互与脚本)都在相同的上下文中运行。换句话说,从任何给定的目录中,如果你执行“python script.py”或“python -i”,cwd、路径和环境将是相同的。
  • 当您说“在迭代模式下”时,您是在谈论运行“python -i”,还是在谈论通过 IDLE 运行?这两者之间肯定存在一些差异。
  • 好问题,布莱恩·奥克利。在这个问题中,我在考虑 python myscript.pypython -i 并手动输入相同的命令。如果您对自己的断言有信心(cwd、路径和环境将相同),我将编辑我的问题以删除我的误导性陈述。
  • Karl Knechtel,我在想“引发异常”或类似的东西。这是您想知道的定义类型吗?我想我并没有想到段错误或崩溃 python 或 BSOD。
  • 有一些方法可以让 CPython 崩溃,如果你足够邪恶,那么实现就无能为力了。但我的意思是:与其尝试编译差异列表,不如向我们展示崩溃的代码以及它是如何崩溃的?

标签: python interactive interactive-mode


【解决方案1】:

Threads 和Greenlets 在交互环境中具有不同的行为。在某些情况下,主事件循环必须被破解。

Greenlet 来自gevent 模块,它是python 中的并发任务。它有一个独立于 Python(pthread)的内部上下文切换,并且并发性非常好(根据我的经验)。 Greenlets 的一些问题是,如果没有猴子补丁(gevent 中的模块),它们会阻止阻塞 C 系统调用和套接字交互。

需要修补主事件循环以使 greenlet 正常工作...如果您在交互式环境中生成 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()

编辑:

在查看了这个项目的一些代码之后,这里是我们如何破解 ipython 输入钩子以使用 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

修补示例:

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是什么。如果你详细说明,它可能会教育我。
  • 伟大的编辑,更多的信息。当然不是我怀疑的任何事情。
【解决方案2】:

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

脚本中的命令会尽快运行,而 REPL 则等待人工输入。

也就是说,您可能遇到了时间问题,即硬件在执行前一个命令后这么快还没有为下一个命令做好准备。

【讨论】:

  • 一个很好的观点。在我引用的特定于硬件的问题中,我将尝试在每个命令之间添加 time.sleep(1)。
  • 好的,我尝试在我的硬件相关问题的所有命令之间添加time.sleep(1)。行为是相同的。所以,这个问题的答案很好,似乎并没有解决另一个问题。
【解决方案3】:

看看这一行

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

如果您可以为 LoadLibrary 使用 COMPLETE 路径

【讨论】:

    猜你喜欢
    • 2010-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-25
    • 2017-02-05
    • 2022-08-22
    • 2022-06-30
    • 1970-01-01
    相关资源
    最近更新 更多