<p>你的代码没有达到你想要的效果。只是<code>sim1</code>实际上并没有调用函数;这样做的语法是<code>sim1()</code></p>
<p>您可以<em>使Python脚本将命令行中的随机字符串作为Python表达式进行计算,但这并不是解决此问题的安全或优雅的方法。相反,将字符串映射到内部函数,这些函数可能具有相同的名称,也可能不具有相同的名称。比如说,</p>
<pre class="lang-py prettyprint-override"><code>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)
</code></pre>
<p>如图所示,您在命令行上接受的符号不需要与要运行的函数的名称相对应。如果您<em>希望</em>成为这种情况,您可以将其简化为使用字典:</p>
<pre class="lang-py prettyprint-override"><code>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')
</code></pre>
<p>这里可能需要注意的是,您可以从命令行中准确地选择要让用户访问的Python符号,并且不允许其他符号泄漏。这将是一个安全问题(想想如果有人传入<code>'import shutil; shutil.rmtree("/")'</code>作为要运行的参数会发生什么)。这在精神上类似于避免<code>eval</code>的许多理由,你会发现谷歌很容易找到这些理由(如果你不熟悉的话,你可能应该这样做)</p>
<p>如果<code>sim1</code>是一个模块名,您只想在用户明确请求时导入它,这也不难做到;请参见<a href="https://stackoverflow.com/questions/13598035/importing-a-module-when-the-module-name-is-in-a-variable">importing a module when the module name is in a variable</a>,但是您不能在脚本的前面部分<code>import</code>使用它</p>
<pre class="lang-py prettyprint-override"><code>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')
</code></pre>
<p>但是一般来说,模块应该只定义函数,并让调用者在调用模块之后的某个时间决定是否以及何时运行它们</p>
<p>也许可以从另一个角度来研究像<code>click</code>这样的第三方库,它很容易让您将所选函数作为Python脚本的“子命令”公开,这与<code>git</code>的子命令<code>init</code>、<code>log</code>等类似</p>