我刚注意到sys.argv在导入的脚本中可见。
A.py
import sys
print("A")
print(sys.argv)
import B
B.py
import sys
print("B")
print(sys.argv)
产量
>> python A.py --foo bar
>> A
>> ['path/to/A.py', '--foo', 'bar']
>> B
>> ['path/to/A.py', '--foo', 'bar']
这很好,因为现在我不必在主脚本(aka.manage.py)中进行参数解析。
问题是:我能依靠这种行为吗?是否存在不起作用的情况?
答案 0 :(得分:5)
模块属性,如sys.argv
是对象。无论您访问哪个模块,它们都是同一个对象。
这也意味着如果一个模块修改sys.argv
,那么该更改也会影响访问sys.argv
的任何其他模块。
关于编码风格的提示:
虽然可能从两个不同的模块访问sys.argv
,但我不推荐它,这就是原因。
我喜欢可以兼作模块的脚本。这为您重用代码提供了最大的灵活性。 sys.argv
仅在代码作为脚本调用时才有意义。为了使代码可用作模块,代码不应依赖于在sys.argv
中查找值。
因此,我建议在主调用脚本中解析sys.argv
一次:
if __name__ == '__main__':
import argparse
def parse_args():
... # argparse uses sys.argv
args = parse_args()
然后根据需要将args
中的值传递给函数。
因此,if __name__ == 'main__'
语句之外的所有内容都不需要依赖sys.argv
,因此可以通过简单的函数调用或模块导入来使用。
答案 1 :(得分:3)
这与sys.argv
的范围无关,特别是所有模块都在一个全局实例中加载。
因此,如果A.py
导入模块然后对其进行修改,如果B.py
导入同一模块,则只能访问导入的模块A.py
。
例如:
A.py
import sys
sys.foo = "foo!"
import B
B.py
import sys
print sys.foo
在此处运行A.py
将导入B.py
,这将有权访问修改后的sys
模块及其中的foo
变量。但是,如果您直接运行B.py,则此代码会引发sys.foo
不存在的错误。
这是一种非常糟糕的行为依赖,因为它对哪个模块导入了非常强大的假设,并且导致极其脆弱的代码。
答案 2 :(得分:1)
sys.argv
)功能在Modules/main.c
中设置了{p> PySys_SetArgv
。
现在, 可能另一个模块也调用PySys_SetArgv
或PySys_SetArgvEx
,但是没有一个标准模块似乎这样做(Python 2.7),并且这样做要么1)成为非常特定的东西的一部分,或2)白痴
所谓的" argv clobbering"有时用于设置流程标题,虽然现代系统提供了更好的方法来执行此操作,但由于C argv
的值在启动时被复制,这不应该是一个问题,即使它会使用。
所以,是的。你可以合理地依赖所有模块中的sys.argv
,尽管有很多方法可以打破它,如果你真的想要的话。
答案 3 :(得分:0)
父脚本启动时设置sys.argv。无论你导入什么,它都不会在任何地方改变。