在Python中使用命令行参数来运行两个脚本之一
在Python中使用命令行参数来运行两个脚本之一
我的包的结构如下:\n
mypackage |-__main__.py |-__init__.py |-model |-__init__.py |-modelfile.py |-simulation |-sim1.py |-sim2.py
\n文件__main__.py
的内容如下:\n
from mypackage.simulation import sim1 if __name__ == '__main__': sim1
\n所以当我执行python -m mypackage
时,脚本sim1.py
会运行。\n现在我想在命令行中添加一个参数,这样python -m mypackage sim1
会运行sim1.py
,python -m mypackage sim2
会运行sim2.py
。\n我尝试了以下代码:\n
import sys from mypackage.simulation import sim1,sim2 if __name__ == '__main__': for arg in sys.argv: arg
\n但它运行了两个脚本,而不是传递的一个脚本。\n在sim1.py
和sim2.py
中,我有以下代码:\n
from mypackage.model import modelfile print('modelfile.ModelClass.someattr')
问题的原因是代码中的sim1
没有调用函数,正确的语法应该是sim1()
。解决方法是在命令行中使用字符串映射到内部函数,并在命令行参数中使用该字符串来调用相应的函数。可以使用if语句来实现这个映射,也可以使用字典来简化代码。使用字典的方法可以确保只允许用户访问命令行中指定的Python符号,避免了安全问题。如果sim1
是一个模块名,而不是一个函数名,可以使用__import__()
函数在用户明确请求时导入模块。另外,建议使用第三方库click
来实现将选定的函数作为Python脚本的“子命令”暴露出来的功能。总之,解决方法主要是使用if语句或字典来实现命令行参数与函数的映射关系,并注意安全问题。
在这个问题中,出现了一个函数被重复调用的情况。当将`sim1`模块导入到`main.py`中,并调用它的函数`simulation1`时,会导致`This is simulation 1`被打印两次。这是因为`simulation1`在`sim1.py`中被调用了一次,在`main.py`中又被调用了一次。
为了解决这个问题,可以将函数`simulation1`放在`if __name__ == "__main__":`语句块中。这样,当`sim1.py`作为主程序被运行时,函数会被执行,而当它被导入到其他模块时,函数不会被执行。
下面是修改后的代码:
sim1.py
def simulation1(): print("This is simulation 1") if __name__ == "__main__": simulation1()
main.py
import sim1 sim1.simulation1()
output
This is simulation 1
通过将函数放在`if __name__ == "__main__":`语句块中,现在只会打印一次`This is simulation 1`。这是因为在`main.py`中导入`sim1`模块时,`if __name__ == "__main__":`语句块不会被执行。只有当`sim1.py`作为主程序被运行时,`if __name__ == "__main__":`语句块才会执行。这样,我们可以控制在不同情况下是否执行函数。
在Python中,通过命令行参数运行两个脚本中的一个脚本,可以使用__import__
函数来导入模块。具体操作如下:
首先,我们有一个主程序example.py
,代码如下:
import sys if __name__ == '__main__': for arg in sys.argv[1:]: module=__import__(arg) print(arg, module.foo(1))
注意,sys.argv[0]
包含程序的名称。
然后,有一个sim1.py
脚本,代码如下:
print('sim1') def foo(n): return n+1
还有一个sim2.py
脚本,代码如下:
print('sim2') def foo(n): return n+2
接着,我们可以通过以下命令来运行程序并输出结果:
python example.py sim1 sim2
输出如下:
sim1 sim1 2 sim2 sim2 3
如果我们使用if __name__ == '__main__': for arg in sys.argv: __import__(arg)
来导入模块,并执行python -m mypackage sim1
命令,将会返回ModuleNotFoundError
错误。
为了解决这个问题,我们需要注意参数的顺序,因为第一个参数是程序的名称,所以我们应该跳过它。具体细节可以参考上面的例子。
然而,即使按照上面的方法进行操作,仍然会出现ModuleNotFoundError
错误。
为了解决这个问题,我们需要将__import__
的结果赋值给全局命名空间,以便将符号名作为模块暴露出来。具体可参考上面的例子。在这个答案中,代码将其赋值给了new_module
,或者在后面的例子中直接丢弃了它。但是,如果所有有用的操作都发生在import
时,能够通过原始名称引用模块似乎并不那么重要。