【问题标题】:Is there a way to test whether a Python function or method has been invoked directly from a shell?有没有办法测试 Python 函数或方法是否直接从 shell 调用?
【发布时间】:2013-01-05 21:56:22
【问题描述】:

添加到rakePHP 的列表:有没有办法测试Python 函数或方法是否已直接从Python shell 调用,而不是从.py 脚本文件中调用?

例如我想定义一个表达式test_expr,当表达式出现在模块“shelltest.py”中时,其行为如下,

#!/usr/bin/python
"""Module shelltest.py"""

def test_expr():
    #...

案例 (1):当直接从 shell 调用时,它产生 True

>>> import shelltest
>>> shelltest.test_expr()
True

案例(2):当导入另一个模块“other.py”并在那里的代码中使用时,它会产生False

#!/usr/bin/python
"""Module other.py"""

import shelltest

def other_func():
    # ...
    shelltest.test_expr()

反过来又从 shell 调用

>>> import other
>>> other.other_func()
False

【问题讨论】:

  • 您能否澄清一下您是在谈论在交互式 shell 中运行东西还是从文件中运行东西,还是在谈论运行东西而不是 import
  • 一般来说,在Python中,你可以自省一切,找出各种各样的东西。但是,无论您根据这些信息在函数中做些什么不同的事情,您可能都不应该这样做。它会使函数变得神奇,因此令人惊讶和困惑。
  • 也许如果您详细说明了您将如何处理这些信息,我们可以帮助您找到一个好的解决方案。
  • 感谢您的澄清。这将很难实现,并且会让您的用户感到困惑。你能解释一下你为什么想要这个以及你会用它做什么吗?可能有更好的方法。
  • @raxacoricofallapatorius:这是个坏主意。异常是 Python 生态系统的真实组成部分,像这样试图通过魔法隐藏它们只会让事情变得困难。改为做简单的事情:让错误像已经打印的那样打印。如果您不喜欢交互式提示显示错误的方式,请查看sys.excepthook

标签: python invoke


【解决方案1】:

如果你在 shell,那么__name__ == '__main__'。 (此外,正如 Ned Batchelder 所说,这只会告诉您函数的定义位置。)

您可能不想在函数中测试它 - 它用于区分模块是否被称为主程序。无论如何,您的函数可能应该以相同的方式工作,如果您需要不同的函数,则应该导入包含相同函数名称的不同模块。

做这样的事情:

if __name__ == '__main__':
   import formain as bumpf
else:
   import forscripts as bumpf

bumpf.domagic()

至于确定您是否处于网络环境中 - 在仅从网络调用的代码中执行此操作。 Python 脚本通常不会被 CGI 调用,因此这并不是真正的用例。

【讨论】:

  • 这只会帮助您确定函数是在 shell 还是文件中定义的,不是吗?它不会让你知道它是如何被调用的。
  • 这不是真的。 docs.python.org/2.7/tutorial/… 表示当模块作为脚本执行时,__name__ 设置为 __main__
  • @Colselaw 这和我说的有什么矛盾?
  • 因为你说的是​​“这只会帮助你确定函数是在 shell 还是文件中定义的,不是吗?它不会让你知道它是如何被调用的。”但是测试__name__ == "__main__" 是您确定模块是从shell 调用还是从另一个模块调用的方式。 (不过,从 REPL 中加载它会给出加载它的模块的 __name__)。
  • @Colselaw 再说一遍,这和我说的有什么矛盾?
【解决方案2】:
>>> import sys
>>> called_via_shell = lambda: sys.stdin.isatty()
>>> called_via_shell()
True

更多信息和代码示例在这里: http://pleac.sourceforge.net/pleac_python/userinterfaces.html#AEN795

【讨论】:

  • 也可以是:called_via_shell = sys.stdin.isatty
  • 如果作为 .py 脚本的一部分执行,这也会给出 True,因此它不会区分我正在寻找的情况。
【解决方案3】:

我最喜欢的检查方法是检查sys.ps1

Python 2.7.3 (default, Aug  1 2012, 05:14:39) 
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> print sys.ps1
'>>> '
$ cat > script.py
#!/usr/bin/env python
import sys
print sys.ps1
$ python script.py 
Traceback (most recent call last):
  File "script.py", line 3, in <module>
    print sys.ps1
AttributeError: 'module' object has no attribute 'ps1'

我认为其他答案是错误的,因为 __name__ 在脚本和交互式 shell 中是 __main__

【讨论】:

  • 这比__main__ 的答案要好,但没有直接说明函数是从shell 调用还是从文件调用。它将准确地指示整个程序是在 shell 中运行还是从文件中运行。
  • Ned,该函数也可以检查sys.ps1。我应该编辑我的答案以包含它吗?
  • 说实话,我并不完全是 OP 想要的。
【解决方案4】:

如果这个 模块 是从 shell 执行的,__name__ 将被设置为 __main__。否则,它将被设置为调用模块的名称。你会一直在模块中看到这个习语:

if __name__ == '__main__':
  # do something with the library

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-30
    • 1970-01-01
    • 2016-10-01
    相关资源
    最近更新 更多