将使用 argparse 的 python script/module 导入另一个 python 脚本
Importing a python script/module that uses argparse into another python script
这个问题可能被认为是多余的,但为了我的辩护,我考虑过类似的问题并给出了解决方案,但它们对我不起作用(或者我只是不理解它们),正如我将展示的那样.
我想做的事情:
当使用 pyinstaller 构建时,我写了几个 python 脚本,它们都是命令行工具(使用 argparse 接受多个参数)。它们在 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 在 .
中的说明
这是我想出的代码 (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 没有输出,我明白这是为什么了。那只是一个测试。但是 运行ning test.py 也会产生错误。我知道为什么这也行不通,但我无法用语言表达。这个 运行() 方法怎么样?拥有它有意义吗?我需要如何修改我的代码才能获得 "What I want to do:" 中描述的双重功能?预先感谢您的帮助!
更新:
我摆脱了错误信息。我改变了,例如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
用于将字典或 keyword=value
对传递给函数。 args = parser.parse_args()
returns 一个 argparse.Namespace
对象,而不是字典。但是 vars(args)
从中生成字典。
In [2]: def foo1(args):
...: print(args)
...: print(args.foo)
...:
In [3]: def foo2(**kwargs):
...: print(kwargs)
...: print(kwargs['foo'])
In [12]: p = argparse.ArgumentParser()
In [13]: p.add_argument('--foo');
In [14]: args = p.parse_args('--foo one'.split())
In [15]: args
Out[15]: Namespace(foo='one')
将args
传递给foo1
:
In [16]: foo1(args)
Namespace(foo='one')
one
尝试 foo2
In [17]: foo2(args)
...
TypeError: foo2() takes 0 positional arguments but 1 was given
In [20]: foo2(**args)
TypeError: foo2() argument after ** must be a mapping, not Namespace
但通过扩展词典版本:
In [18]: vars(args)
Out[18]: {'foo': 'one'}
In [19]: foo2(**vars(args))
{'foo': 'one'}
one
感谢所有回复的人。在一位同事的帮助下,我得到了问题的答案。这是功能代码:
wc_query_test.py:
import sys
import argparse
import getpass
def main(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']
# The parser is only called if this script is called as a script/executable (via command line) but not when imported by another script
if __name__=='__main__':
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://webctrl.rz-berlin.mpg.de',
help="URL of the WebCTRL server as e.g. http://google.de")
args = parser.parse_args()
# Convert the argparse.Namespace to a dictionary: vars(args)
main(vars(args))
sys.exit(0)
现在,有三种执行方式 wc_query_test 这是我想要实现的:
1) 从命令行调用 wc_query_test.py:
~/PycharmProjects/webctrl$ python wc_query_test.py -u aawrg -p wgAWER -n YWERGAEWR
2) 从命令行编译和调用wc_query_test:
~/PycharmProjects/webctrl$ pyinstaller --distpath dist/. wc_query_test.py
~/PycharmProjects/webctrl$ ./dist/wc_query_test/wc_query_test -u aawrg -p wgAWER -n YWERGAEWR
3) 从另一个 python 脚本调用 wc_query_test 进入模块类型用法的方向:
import wc_query_test
myDictonary = {'username':'wsdl', 'password':'aaaaaa', 'node':'/trees/geographic', 'url':'https://my.server.de'}
wc_query_test.main(myDictonary)
所有三个版本都产生与预期相同的输出,例如:
~/PycharmProjects/webctrl$ ./dist/wc_query_test/wc_query_test -u aawrg -p wgAWER -n YWERGAEWR
Username: aawrg
Node: YWERGAEWR
URL: https://webctrl.rz-berlin.mpg.de
这个问题可能被认为是多余的,但为了我的辩护,我考虑过类似的问题并给出了解决方案,但它们对我不起作用(或者我只是不理解它们),正如我将展示的那样.
我想做的事情: 当使用 pyinstaller 构建时,我写了几个 python 脚本,它们都是命令行工具(使用 argparse 接受多个参数)。它们在 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 在
这是我想出的代码 (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 没有输出,我明白这是为什么了。那只是一个测试。但是 运行ning test.py 也会产生错误。我知道为什么这也行不通,但我无法用语言表达。这个 运行() 方法怎么样?拥有它有意义吗?我需要如何修改我的代码才能获得 "What I want to do:" 中描述的双重功能?预先感谢您的帮助!
更新:
我摆脱了错误信息。我改变了,例如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
用于将字典或 keyword=value
对传递给函数。 args = parser.parse_args()
returns 一个 argparse.Namespace
对象,而不是字典。但是 vars(args)
从中生成字典。
In [2]: def foo1(args):
...: print(args)
...: print(args.foo)
...:
In [3]: def foo2(**kwargs):
...: print(kwargs)
...: print(kwargs['foo'])
In [12]: p = argparse.ArgumentParser()
In [13]: p.add_argument('--foo');
In [14]: args = p.parse_args('--foo one'.split())
In [15]: args
Out[15]: Namespace(foo='one')
将args
传递给foo1
:
In [16]: foo1(args)
Namespace(foo='one')
one
尝试 foo2
In [17]: foo2(args)
...
TypeError: foo2() takes 0 positional arguments but 1 was given
In [20]: foo2(**args)
TypeError: foo2() argument after ** must be a mapping, not Namespace
但通过扩展词典版本:
In [18]: vars(args)
Out[18]: {'foo': 'one'}
In [19]: foo2(**vars(args))
{'foo': 'one'}
one
感谢所有回复的人。在一位同事的帮助下,我得到了问题的答案。这是功能代码:
wc_query_test.py:
import sys
import argparse
import getpass
def main(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']
# The parser is only called if this script is called as a script/executable (via command line) but not when imported by another script
if __name__=='__main__':
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://webctrl.rz-berlin.mpg.de',
help="URL of the WebCTRL server as e.g. http://google.de")
args = parser.parse_args()
# Convert the argparse.Namespace to a dictionary: vars(args)
main(vars(args))
sys.exit(0)
现在,有三种执行方式 wc_query_test 这是我想要实现的:
1) 从命令行调用 wc_query_test.py:
~/PycharmProjects/webctrl$ python wc_query_test.py -u aawrg -p wgAWER -n YWERGAEWR
2) 从命令行编译和调用wc_query_test:
~/PycharmProjects/webctrl$ pyinstaller --distpath dist/. wc_query_test.py
~/PycharmProjects/webctrl$ ./dist/wc_query_test/wc_query_test -u aawrg -p wgAWER -n YWERGAEWR
3) 从另一个 python 脚本调用 wc_query_test 进入模块类型用法的方向:
import wc_query_test
myDictonary = {'username':'wsdl', 'password':'aaaaaa', 'node':'/trees/geographic', 'url':'https://my.server.de'}
wc_query_test.main(myDictonary)
所有三个版本都产生与预期相同的输出,例如:
~/PycharmProjects/webctrl$ ./dist/wc_query_test/wc_query_test -u aawrg -p wgAWER -n YWERGAEWR
Username: aawrg
Node: YWERGAEWR
URL: https://webctrl.rz-berlin.mpg.de