1 文件(夹)结构
(base) t@t-virtual-machine:~/PycharmProjects/ParserLearning$ tree -L 3 . ├── README.md ├── setup.cfg ├── setup.py ├── ttest │ ├── __init__.py │ ├── __main__.py │ ├── main.py │ ├── parser.py │ ├── testfunc │ │ ├── __init__.py │ │ └── prtTips.py │ └── __version__.py └── venv
2 文件内容
README.md
# This is a readme.md files.
# setup.cfg
[metadata]
name = ttest
version = attr: ttest.__version__
[options]
zip_safe = False
# Very important!
# 自动搜索存在__init__.py的文件夹作为包!!!!!!!!!
packages = find:
# 因为例子里没涉及到其他操作,这里只要求1个必须的包
install_requires =
argcomplete ~= 1.9.4
python_requires = ~= 3.7
[options.entry_points]
console_scripts =
ttest = ttest.__main__:main
# ttest包内,必须有一个__main__.py文件,该文件内部,必须定义了[def main():]
# setup.py
#!/usr/bin/env python3
"""Metadata for package to allow installation with pip."""
import setuptools
import os
import subprocess
with open("README.md", "r") as fh:
long_description = fh.read()
# 执行指定位置下的文件内容读取操作,不打印
exec(open(os.path.join("ttest", "__version__.py")).read())
# 获取当前.py文件所在的文件夹路径
print(os.path.dirname(__file__))
# 执行指定文件夹下的.py文件,类似于直接命令行执行:env python3 xxx.py
# subprocess.run(['env', 'python3', os.path.join(os.path.dirname(__file__), 'refresh_version.py')])
# 进一步理解(必须安装了tree)
subprocess.run(['tree', '-L', '1'])
setuptools.setup(
name="ttest",
description="test parser by tao.",
author="tao",
author_email="tideal@qq.com",
version=__version__,
url="https://tideal.github.io/blogs/",
packages=setuptools.find_packages(),
tests_require=[
],
classifiers=[
"Programming Language :: Python :: 3",
"License :: OSI Approved :: MIT License",
]
)
# ttest/__init__.py
# 从当前包内的parser.py文件中导入parser函数,并且执行该函数
# [.parser] 意味着 .../parser.py
from .parser import parser
parser()
from ttest.__version__ import __version__
# 从.../ttest/main.py 导入函数 main()
# if no this, error tips: -> AttributeError: module 'ttest' has no attribute 'main'
from ttest.main import main
# 导入.../ttest/testfunc 包,即导入testfunc包内的__init__.py文件
# must have this:
import ttest.testfunc as testfunc
# ttest/__main__.py
""" __main__.py
"""
# PYTHON_ARGCOMPLETE_OK
import ttest
# setup.cfg 入口函数
def main():
# 放这句话的原因是,验证自己的猜想,结果表明,执行的是这段代码!
print("Enter into [__main__.py -> main()]...")
ttest.main()
if __name__ == '__main__':
# 放这句话的原因是,验证自己的猜想,结果表明:这段代码根本没执行!
print("Enter into [__main__.py -> if]...")
ttest.main()
# ttest/main.py
import ttest
import sys
# print(">>>>>>>> xxx")为调试作用
def main(args=None):
"""Command-line interface entry point."""
print("Enter into [main.py -> main()]...")
print(">>>>>>>> line 1")
parser = ttest.parser()
print(">>>>>>>> line 2")
print(">>>>>>>> line 2-1 args:")
print(args)
args = parser.parse_args(args)
print(">>>>>>>> line 2-2 args:")
print(args)
print(args.func)
print(">>>>>>>> line 3")
try:
print(">>>>>>>> line 4-1")
func = eval(args.func)
print(">>>>>>>> line 4-2")
except AttributeError:
print(">>>>>>>> line 5-1")
parser.print_help()
print(">>>>>>>> line 5-2")
sys.exit(0)
print(">>>>>>>> line 6")
print(">>>>>>>> line 7 args:")
print(args)
func(args)
if __name__ == '__main__':
print("Enter into [main.py -> if]...")
main()
学习文档@官方文档
# ttest/parser.py
def parser():
"""Returns parser for ttest."""
import argparse
import argcomplete
from . import __version__
parser = argparse.ArgumentParser(
description='\n'.join([
"ttest",
"--------",
"Version: {}".format(__version__),
]),
formatter_class=argparse.RawTextHelpFormatter,
)
parser.add_argument(
'-v',
'--version',
action='version',
version=__version__,
)
subparsers = parser.add_subparsers()
t_parser = subparsers.add_parser("run_t", help="t model")
t_parser.add_argument("--func_tips", type=str, default=None, help="test the function of subparsers")
# 一直写到函数名:
'''对于代码ttest.testfunc.prtTips2:
[ttest.testfunc] 指代的是:parser.py所在包ttest下的testfunc包中的__init__.py文件;
[prtTips2]指代的是:__init__.py文件中已添加的函数名'''
t_parser.set_defaults(func="ttest.testfunc.prtTips2")
argcomplete.autocomplete(parser)
return parser
# ttest/__version__.py
__version__ = "1.0"
# ttest/testfunc/__init__.py
# 准备在parser.set_defaults(func=xxx)里的xxx必须要在__int__.py中导入
# 从../ttest/testfunc/prtTips.py中导入函数:prtTips1, prtTips2(两个函数调用,以示区分)
''' !!!!本行代码:
from .prtTips import prtTips1, prtTips2
与ttest/__init__.py中的代码:
import ttest.testfunc as testfunc,
结合,即可以用在parser.py文件中,实现:
t_parser.set_defaults(func="ttest.testfunc.prtTips2")
'''
from .prtTips import prtTips1, prtTips2
# ttest/testfunc/prtTips.py
def prtTips1(args=None):
print("This is a tips1:")
print("hello, current directory is ttest.testfunc.prtTips.prtTips1")
def prtTips2(args=None):
print("This is a tips2:")
print("hello, current directory is ttest.testfunc.prtTips.prtTips2")
3 操作命令
3.1 命令行输入,打包,并安装
python setup.py install
3.2 键入命令,查看包
pip list
3.3 用包名执行 -h 帮助菜单
usage: ttest [-h] [-v] {run_t} ...
3.4 按照帮助菜单,键入命令
ttest run_t
or
ttest run_t --func_tips t
解释
“
ttest“包名,也是执行的命令“
run_t“是选择参数(只有这一个参数),要么选,要么不选“
--func_tips“是可选参数“
t“是--func_tips明确指示的输入参数,类型默认为type=str
4 执行结果
(venv) (base) t@t-virtual-machine:~/PycharmProjects/ParserLearning$ ttest run_t
#-----------------------------------------------------
Enter into [__main__.py -> main()]...
Enter into [main.py -> main()]...
>>>>>>>> line 1
>>>>>>>> line 2
>>>>>>>> line 2-1 args:
None
>>>>>>>> line 2-2 args:
Namespace(func='ttest.testfunc.prtTips2', func_tips=None)
ttest.testfunc.prtTips2
>>>>>>>> line 3
>>>>>>>> line 4-1
>>>>>>>> line 4-2
>>>>>>>> line 6
>>>>>>>> line 7 args:
Namespace(func='ttest.testfunc.prtTips2', func_tips=None)
This is a tips2:
hello, current directory is ttest.testfunc.prtTips.prtTips2
(venv) (base) t@t-virtual-machine:~/PycharmProjects/ParserLearning$ ttest run_t --func_tips t
#-----------------------------------------------------
Enter into [__main__.py -> main()]...
Enter into [main.py -> main()]...
>>>>>>>> line 1
>>>>>>>> line 2
>>>>>>>> line 2-1 args:
None
>>>>>>>> line 2-2 args:
Namespace(func='ttest.testfunc.prtTips2', func_tips='t')
ttest.testfunc.prtTips2
>>>>>>>> line 3
>>>>>>>> line 4-1
>>>>>>>> line 4-2
>>>>>>>> line 6
>>>>>>>> line 7 args:
Namespace(func='ttest.testfunc.prtTips2', func_tips='t')
This is a tips2:
hello, current directory is ttest.testfunc.prtTips.prtTips2