有没有办法测试Python函数或方法是否已直接从shell调用?

有没有办法测试Python函数或方法是否已直接从shell调用?,python,invoke,Python,Invoke,添加到和的列表中:是否有一种方法可以测试Python函数或方法是否直接从Python shell调用,而不是从.py脚本文件中调用 例如,我想定义一个表达式,test\u expr,当该表达式出现在模块“shelltest.py”中时,其行为如下所示 案例(1):当直接从shell调用时,它产生True >>> import shelltest >>> shelltest.test_expr() True >>> import other

添加到和的列表中:是否有一种方法可以测试Python函数或方法是否直接从Python shell调用,而不是从
.py
脚本文件中调用

例如,我想定义一个表达式,
test\u expr
,当该表达式出现在模块“shelltest.py”中时,其行为如下所示

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

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

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

import shelltest

def other_func():
    # ...
    shelltest.test_expr()
然后从shell调用

>>> import shelltest
>>> shelltest.test_expr()
True
>>> import other
>>> other.other_func()
False

如果您在shell中,那么
\uuuuuu name\uuuuuu=='\uuuuuu main\uuuuu'
。(此外,正如Ned Batchelder所指出的,这只会告诉您函数的定义位置。)

您可能不想在函数中测试这一点,而是用它来区分模块是否被作为主程序调用。不管怎样,您的函数都应该以相同的方式工作,如果您需要不同的函数,则应该导入包含相同函数名的不同模块

这样做:

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

bumpf.domagic()

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

如果这个模块是从shell执行的,
\uuu name\uuuu
将设置为
\uu main\uu
。否则,它将被设置为调用模块的名称。您将一直在模块中看到这种习惯用法:

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

我最喜欢的检查方法是检查
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'
Python 2.7.3(默认,2012年8月1日05:14:39)
[GCC 4.6.3]关于linux2
有关详细信息,请键入“帮助”、“版权”、“信用证”或“许可证”。
>>>打印系统ps1
'>>> '
$cat>script.py
#!/usr/bin/env python
导入系统
打印系统ps1
$python script.py
回溯(最近一次呼叫最后一次):
文件“script.py”,第3行,在
打印系统ps1
AttributeError:“模块”对象没有属性“ps1”
我认为其他答案是错误的,因为脚本和交互式shell中的
\uuuu name\uuuuuuuu
\uuuuuuuuu\uuuu

>>> import sys
>>> called_via_shell = lambda: sys.stdin.isatty()
>>> called_via_shell()
True
更多信息和代码示例如下:

您能否澄清一下,您是在交互式shell中运行东西还是从文件中运行,还是在谈论运行某个东西还是导入某个
?通常,在Python中,您可以反省一切,并找出各种各样的东西。但是,无论您根据这些信息在函数中做什么不同的操作,您可能都不应该这样做。这将使函数变得神奇,因此令人惊讶和困惑。如果您详细说明如何处理这些信息,我们可以帮助您找到一个好的解决方案。感谢您的澄清。这将很难实现,并且会让您的用户感到困惑。你能解释一下你为什么想要这个,你会用它做什么吗?也许有更好的办法。@raxacoricofallapatorius:这是个坏主意。异常是Python生态系统的一个真实组成部分,试图通过这样的魔法来隐藏它们只会让事情变得困难。改为做一件简单的事情:让错误像以前一样打印出来。如果您不喜欢交互式提示显示错误的方式,请查看
sys.excepthook
。这只会帮助您确定函数是在shell还是文件中定义的,不是吗?它并没有给你一个关于它是如何被调用的线索,那不是真的。表示当模块作为脚本执行时,
\uuuuuu name\uuuuuu
被设置为
\uuuu main\uuuuuuu
。@Colselaw这与我说的有什么矛盾?因为你说的是“这只会帮助你弄清楚函数是在shell中定义的还是在文件中定义的,不?它不会给你一个关于它是如何被调用的线索。”但是测试
\uuuuu name\uuuu==“\uuuuu main\uuuuu”
是如何确定一个模块是从shell还是从另一个模块调用的。(从REPL加载它会给出加载它的模块的
\uu name.
。@Colselaw再说一次,这与我所说的有什么矛盾?这比
\uu main.
答案要好,但不能直接说明函数是从shell还是从文件调用的。它将准确地指示程序作为一个整体是在shell中运行还是从文件中运行。此外,该函数还可以检查sys.ps1。我应该编辑我的答案来包含它吗?老实说,我不知道OP到底想要什么。最好是:
通过@u shell=sys.stdin.isatty调用。\u如果作为
.py
脚本的一部分执行,这也会为真,因此它不会区分我要查找的案例。