这个问题可能被认为是多余的,但为了辩护,我考虑了类似的问题并给出了解决方案,但它们对我不起作用(或者我只是没有理解),我将展示原因。
我编写了一些Python脚本,它们都是命令行工具(使用argparse接受几个参数),使用pyinstaller构建时正常工作。它们在PyCharm终端和Ubuntu终端中都能按预期工作。现在,我想让每个脚本成为一个模块,可以从另一个Python脚本中调用,传递所需的参数,就像在终端中做的那样。
这是其中一个原始脚本(我缩短了脚本,以便它作为最小示例):
就像我之前说的,在我的IDE(Pycharm)内部...
当我在Python终端运行它时,我得到了以下输出:
运行 wc_query_test.py 没有输出,我知道为什么。那只是一个测试。但是运行 test.py 也会出现错误。我有个想法为什么这不起作用,但我无法用语言表达出来。run()方法怎么样?有它存在的意义吗?我需要如何修改代码才能获得“我想要做的事情”中描述的双重功能?感谢您提前的帮助!
更新: 我摆脱了错误消息。例如,我将 kwargs.username 改为 kwargs.get('username'),因为 kwargs 是一个字典。现在代码看起来像这样:
在Python终端中运行它,得到了预期的结果:
我该如何修改 wc_query_test.py 使其接受参数并作为命令行工具使用?
我编写了一些Python脚本,它们都是命令行工具(使用argparse接受几个参数),使用pyinstaller构建时正常工作。它们在PyCharm终端和Ubuntu终端中都能按预期工作。现在,我想让每个脚本成为一个模块,可以从另一个Python脚本中调用,传递所需的参数,就像在终端中做的那样。
这是其中一个原始脚本(我缩短了脚本,以便它作为最小示例):
import sys
import argparse
import getpass
if len(sys.argv) < 2:
print "You haven't specified any arguments. Use -h to get more details on how to use this command."
sys.exit(1)
parser = argparse.ArgumentParser()
parser.add_argument('--username', '-u', type=str, default=None, help='Username for the login to the WebCTRL server')
parser.add_argument('--password', '-p', type=str, default=None, help='Password for the login to the WebCTRL server')
parser.add_argument('--node', '-n', type=str, default=None,
help='Path to the point or node whose children you want to retrieve. Start querying at the lowest level with "-n /trees/geographic"')
parser.add_argument('-url', type=str, default='https://my.server.de',
help="URL of the WebCTRL server as e.g. http://google.de")
args = parser.parse_args()
if args.username is None:
print 'No user name specified. Login to WebCTRL needs a user name and password. Check all options for this command via -h'
sys.exit(1)
else:
username = args.username
if args.password is None:
password = getpass.getpass('No password specified via -p. Please enter your WebCTRL login password: ')
else:
password = args.password
if args.node is None:
print 'No path to a node specified. Check all options for this command via -h'
sys.exit(1)
if args.url is None:
print 'No URL given. Specify the URL to the WebCTRL server analogous to http://google.de'
sys.exit(1)
else:
wsdlFile = args.url + '/_common/webservices/Eval?wsdl'
# This doesn't belong to my original code. It's rather for demonstration:
# Print the arguments and leave the script
print 'Username: ' + args.username
print 'Node: ' + args.node
print 'URL: ' + args.url
sys.exit(0)
就像我之前说的,在我的IDE(Pycharm)内部...
$ python wc_query_test.py -u wsdl -n /trees/geographic
No password specified via -p. Please enter your WebCTRL login password:
Username: wsdl
Node: /trees/geographic
URL: https://my.server.de
...而且在Ubuntu终端中它可以正常工作:
$ pyinstaller --distpath dist/. wc_query_test.py
$ ./dist/wc_query_test/wc_query_test -u wsdl -n /trees/geographic
No password specified via -p. Please enter your WebCTRL login password:
Username: wsdl
Node: /trees/geographic
URL: https://my.server.de
接下来是实际问题: 我希望脚本wc_query_test.py能够成为一个模块,可以被导入到另一个Python脚本中并在那里执行,就像在命令行中传递参数一样。为了实现这一点,我遵循了@Waylan在这个stackoverflow问题中的指示。
这是我设计的代码(wc_query_test.py):
import sys
import argparse
import getpass
def main(**kwargs):
if kwargs.username is None:
print 'No user name specified. Login to WebCTRL needs a user name and password. Check all options for this command via -h'
sys.exit(1)
else:
username = kwargs.username
if kwargs.password is None:
password = getpass.getpass('No password specified via -p. Please enter your WebCTRL login password: ')
else:
password = kwargs.password
if kwargs.node is None:
print 'No path to a node specified. Check all options for this command via -h'
sys.exit(1)
if kwargs.url is None:
print 'No URL given. Specify the URL to the WebCTRL server analogous to http://google.de'
sys.exit(1)
else:
wsdlFile = kwargs.url + '/_common/webservices/Eval?wsdl'
# This doesn't belong to my original code. It's rather for demonstration:
# Print the arguments and leave the script
print 'Username: ' + username
print 'Node: ' + kwargs.node
print 'URL: ' + kwargs.url
sys.exit(0)
def run():
parser = argparse.ArgumentParser()
parser.add_argument('--username', '-u', type=str, default=None, help='Username for the login to the WebCTRL server')
parser.add_argument('--password', '-p', type=str, default=None, help='Password for the login to the WebCTRL server')
parser.add_argument('--node', '-n', type=str, default=None,
help='Path to the point or node whose children you want to retrieve. Start querying at the lowest level with "-n /trees/geographic"')
parser.add_argument('-url', type=str, default='https://my.server.de',
help="URL of the WebCTRL server as e.g. http://google.de")
args = parser.parse_args()
main(**args)
以下是导入模块并调用它的脚本(test.py):
import wc_query_test
wc_query_test.main(username='wsdl', password='aaaaaa', node='/trees/geographic')
当我在Python终端运行它时,我得到了以下输出:
~/PycharmProjects/webctrl$ python wc_query_test.py
~/PycharmProjects/webctrl$ python test.py
Traceback (most recent call last):
File "test.py", line 3, in <module>
wc_query_test.main(username='wsdl', password='aaaaaa', node='/trees/geographic/#geb_g', url='https://webctrl.rz-berlin.mpg.de')
File "/home/stefan/PycharmProjects/webctrl/wc_query_test.py", line 23, in main
if kwargs.username is None:
AttributeError: 'dict' object has no attribute 'username'
运行 wc_query_test.py 没有输出,我知道为什么。那只是一个测试。但是运行 test.py 也会出现错误。我有个想法为什么这不起作用,但我无法用语言表达出来。run()方法怎么样?有它存在的意义吗?我需要如何修改代码才能获得“我想要做的事情”中描述的双重功能?感谢您提前的帮助!
更新: 我摆脱了错误消息。例如,我将 kwargs.username 改为 kwargs.get('username'),因为 kwargs 是一个字典。现在代码看起来像这样:
import sys
import argparse
import getpass
def main(**kwargs):
if kwargs.get('username') is None:
print 'No user name specified. Login to WebCTRL needs a user name and password. Check all options for this command via -h'
sys.exit(1)
else:
username = kwargs.get('username')
if kwargs.get('password') is None:
password = getpass.getpass('No password specified via -p. Please enter your WebCTRL login password: ')
else:
password = kwargs.get('password')
if kwargs.get('node') is None:
print 'No path to a node specified. Check all options for this command via -h'
sys.exit(1)
if kwargs.get('url') is None:
print 'No URL given. Specify the URL to the WebCTRL server analogous to http://google.de'
sys.exit(1)
else:
wsdlFile = kwargs.get('url') + '/_common/webservices/Eval?wsdl'
# This doesn't belong to my original code. It's rather for demonstration:
# Print the arguments and leave the script
print 'Username: ' + username
print 'Node: ' + kwargs.get('node')
print 'URL: ' + kwargs.get('url')
sys.exit(0)
def run():
parser = argparse.ArgumentParser()
parser.add_argument('--username', '-u', type=str, default=None, help='Username for the login to the WebCTRL server')
parser.add_argument('--password', '-p', type=str, default=None, help='Password for the login to the WebCTRL server')
parser.add_argument('--node', '-n', type=str, default=None,
help='Path to the point or node whose children you want to retrieve. Start querying at the lowest level with "-n /trees/geographic"')
parser.add_argument('-url', type=str, default='https://webctrl.rz-berlin.mpg.de',
help="URL of the WebCTRL server as e.g. http://google.de")
args = parser.parse_args()
main(**args)
在Python终端中运行它,得到了预期的结果:
$ python test.py
Username: wsdl
Node: /trees/geographic
URL: https://my.server.de
但是通过pyinstaller构建并作为命令行工具运行它时,没有输出:
~/PycharmProjects/webctrl$ ./dist/wc_query_test/wc_query_test -h
~/PycharmProjects/webctrl$
我该如何修改 wc_query_test.py 使其接受参数并作为命令行工具使用?
kwargs
是一个字典,没有 'username' 属性,就像错误所述。你想要访问项:kwargs['username']
。请注意,main(**args)
也会失败,因为parse_args()
返回的Namespace
对象不是映射。一个快速而简单的解决方案是使用main(**vars(args))
。 - Ilja Everilämain()
函数不应该打印错误消息并调用sys.exit()
,而是应该引发异常(带有错误消息)。 - bruno desthuilliersif __name__
块中调用解析器。这样只有当脚本作为脚本被调用时才会使用它,而不是被另一个脚本导入时也运行解析器。在几个被导入的脚本中运行解析器会引发麻烦。 - hpaulj