繁体   English   中英

python 中的命令行参数运行两个脚本之一

[英]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.pypython -m mypackage sim2 sim2 运行sim2.py

我试过以下方法:

import sys
from mypackage.simulation import sim1,sim2

if __name__ == '__main__':
    for arg in sys.argv:
        arg

但它同时运行这两个脚本,而不是传入参数。

sim1.pysim2.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 次。 因为, simulation1sim1.pymain.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具有子命令initlog等的方式类似。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM