[英]Command line argument in python to run one of two scripts
我的 package 结构如下:
mypackage
|-__main__.py
|-__init__.py
|-model
|-__init__.py
|-modelfile.py
|-simulation
|-sim1.py
|-sim2.py
文件__main__.py
的内容是
from mypackage.simulation import sim1
if __name__ == '__main__':
sim1
这样当我执行python -m mypackage
时,脚本sim1.py
运行。 现在我想在命令行中添加一个参数,以便python -m mypackage sim1
运行sim1.py
和python -m mypackage sim2
sim2 运行sim2.py
。
我试过以下方法:
import sys
from mypackage.simulation import sim1,sim2
if __name__ == '__main__':
for arg in sys.argv:
arg
但它同时运行这两个脚本,而不是传入参数。
在sim1.py
和sim2.py
我有以下代码
from mypackage.model import modelfile
print('modelfile.ModelClass.someattr')
您可以简单地使用模块名称作为参数调用__import__
,例如:
new_module = __import__(arg)
在你的循环中。
因此,例如,您有一个名为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
output:
sim1
sim1 2
sim2
sim2 3
假设您有包含以下内容的文件。
sim1.py
def simulation1():
print("This is simulation 1")
simulation1()
main.py
import sim1
sim1.simulation1()
output
This is simulation 1
This is simulation 1
当您将sim1
导入main.py
并调用其 function simulation1
时, This is simulation 1
被打印 2 次。 因为, simulation1
在sim1.py
和main.py
中被调用。
如果您想在 sim1.py 中运行sim1.py
,但又不想在导入sim1
时运行,则可以将其放在if __name__ == "__main__":
中。
sim1.py
def simulation1():
print("This is simulation 1")
if __name__ == "__main__":
simulation1()
main.py
import sim1
sim1.simulation1()
output
This is simulation 1
你的代码没有做你想做的事。 只是sim1
实际上并没有调用 function; 这样做的语法是sim1()
。
您可以让您的 Python 脚本将命令行中的随机字符串评估为 Python 表达式,但这确实不是解决此问题的安全或优雅的方法。 相反,将字符串 map 用于内部函数,这些函数可能具有相同的名称,也可能不同。 例如,
if __name__ == '__main__':
import sys
for arg in sys.argv[1:]:
if arg == 'sim1':
sim1()
if arg == 'mustard':
sim2()
if arg == 'ketchup':
sim3(sausages=2, cucumber=user in cucumberlovers)
else:
raise ValueError('Anguish! Don\'t know how to handle %s' % arg)
正如这应该说明的那样,您在命令行上接受的符号不需要与您要运行的 function 的名称相对应。 如果您希望这样,您可以简化它以使用字典:
if __name__ == '__main__':
import sys
d = {fun.__name__: fun for fun in (sim1, sim2)}
for arg in sys.argv[1:]:
if arg in d:
d[arg]()
else:
raise ValueError('Anguish! etc')
这里可能需要注意的重要一点是,您 select 正是您想让用户从命令行访问的 Python 符号,并且不允许其他人泄漏。 这将是一个安全问题(想想如果有人传入'import shutil; shutil.rmtree("/")'
作为运行参数会发生什么)。 这在精神上类似于避免eval
的许多很多原因,你会发现很容易用谷歌搜索(如果你不熟悉,你可能应该这样做)。
如果sim1
是您只想在用户特别请求时才导入的模块名称,那也不难做到; 请参阅当模块名称位于变量中时导入模块,但您无法在脚本中更早地import
它。
if __name__ == '__main__':
import sys
modules = ['sim1', 'sim2']
for arg in sys.argv[1:]:
if arg in modules:
globals()[arg] = __import__(arg)
else:
raise ValueError('Anguish! etc')
但一般来说,模块应该只定义函数,并让调用者在import
模块后的某个时间决定是否以及何时运行它们。
也许切线地查看第三方库,例如click
,它可以轻松地将所选功能公开为 Python 脚本的“子命令”,这与git
具有子命令init
、 log
等的方式类似。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.