easy-use-tools 1.0.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- easy_use_tools-1.0.1/LICENSE +19 -0
- easy_use_tools-1.0.1/PKG-INFO +63 -0
- easy_use_tools-1.0.1/README.md +37 -0
- easy_use_tools-1.0.1/easy_use_tools/__init__.py +1 -0
- easy_use_tools-1.0.1/easy_use_tools/core/__init__.py +1 -0
- easy_use_tools-1.0.1/easy_use_tools/manage.py +3 -0
- easy_use_tools-1.0.1/easy_use_tools/utils/__init__.py +1 -0
- easy_use_tools-1.0.1/easy_use_tools/utils/common.py +80 -0
- easy_use_tools-1.0.1/easy_use_tools/utils/linux/__init__.py +1 -0
- easy_use_tools-1.0.1/easy_use_tools/utils/log.py +179 -0
- easy_use_tools-1.0.1/easy_use_tools/utils/windows/__init__.py +1 -0
- easy_use_tools-1.0.1/easy_use_tools.egg-info/PKG-INFO +63 -0
- easy_use_tools-1.0.1/easy_use_tools.egg-info/SOURCES.txt +17 -0
- easy_use_tools-1.0.1/easy_use_tools.egg-info/dependency_links.txt +1 -0
- easy_use_tools-1.0.1/easy_use_tools.egg-info/entry_points.txt +2 -0
- easy_use_tools-1.0.1/easy_use_tools.egg-info/requires.txt +3 -0
- easy_use_tools-1.0.1/easy_use_tools.egg-info/top_level.txt +1 -0
- easy_use_tools-1.0.1/setup.cfg +4 -0
- easy_use_tools-1.0.1/setup.py +79 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
Copyright (c) 2021 The Python Packaging Authority
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
5
|
+
in the Software without restriction, including without limitation the rights
|
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
8
|
+
furnished to do so, subject to the following conditions:
|
|
9
|
+
|
|
10
|
+
The above copyright notice and this permission notice shall be included in all
|
|
11
|
+
copies or substantial portions of the Software.
|
|
12
|
+
|
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
19
|
+
SOFTWARE.
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: easy_use_tools
|
|
3
|
+
Version: 1.0.1
|
|
4
|
+
Summary: An easy use tools package
|
|
5
|
+
Home-page: https://github.com/XXX
|
|
6
|
+
Author: yuanyang.li
|
|
7
|
+
Author-email: yuanyang.edison.li@gmail.com
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: Operating System :: OS Independent
|
|
10
|
+
Requires-Python: >=3.8
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Requires-Dist: requests>=2.25.1
|
|
14
|
+
Requires-Dist: numpy>=1.19.5
|
|
15
|
+
Requires-Dist: shortuuid
|
|
16
|
+
Dynamic: author
|
|
17
|
+
Dynamic: author-email
|
|
18
|
+
Dynamic: classifier
|
|
19
|
+
Dynamic: description
|
|
20
|
+
Dynamic: description-content-type
|
|
21
|
+
Dynamic: home-page
|
|
22
|
+
Dynamic: license-file
|
|
23
|
+
Dynamic: requires-dist
|
|
24
|
+
Dynamic: requires-python
|
|
25
|
+
Dynamic: summary
|
|
26
|
+
|
|
27
|
+
# 通用工具集
|
|
28
|
+
这是一个通用工具集, 适用于>=Python3.8
|
|
29
|
+
|
|
30
|
+
## 1. 准备
|
|
31
|
+
### 1.1 安装依赖
|
|
32
|
+
```
|
|
33
|
+
pip3 install --upgrade packaging setuptools wheel twine
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## 2. 命令说明
|
|
37
|
+
### 2.1 本地安装使用
|
|
38
|
+
```
|
|
39
|
+
python setup.py install
|
|
40
|
+
```
|
|
41
|
+
### 2.2 打包
|
|
42
|
+
```
|
|
43
|
+
python setup.py sdist bdist_wheel
|
|
44
|
+
```
|
|
45
|
+
在当前dist目录下的两个文件是要上传到 PyPi 网站上供别人下载安装的(*.tar.gz、*.whl)
|
|
46
|
+
|
|
47
|
+
### 2.3 配置文件检查
|
|
48
|
+
```
|
|
49
|
+
python3 setup.py check
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### 2.4 上传前检查
|
|
53
|
+
```
|
|
54
|
+
twine check dist/*
|
|
55
|
+
```
|
|
56
|
+
### 2.4 执行上传
|
|
57
|
+
```
|
|
58
|
+
twine upload dist/*
|
|
59
|
+
```
|
|
60
|
+
### 2.5 清理
|
|
61
|
+
```
|
|
62
|
+
rm -rf build/ dist/ *.egg-info/
|
|
63
|
+
```
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# 通用工具集
|
|
2
|
+
这是一个通用工具集, 适用于>=Python3.8
|
|
3
|
+
|
|
4
|
+
## 1. 准备
|
|
5
|
+
### 1.1 安装依赖
|
|
6
|
+
```
|
|
7
|
+
pip3 install --upgrade packaging setuptools wheel twine
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
## 2. 命令说明
|
|
11
|
+
### 2.1 本地安装使用
|
|
12
|
+
```
|
|
13
|
+
python setup.py install
|
|
14
|
+
```
|
|
15
|
+
### 2.2 打包
|
|
16
|
+
```
|
|
17
|
+
python setup.py sdist bdist_wheel
|
|
18
|
+
```
|
|
19
|
+
在当前dist目录下的两个文件是要上传到 PyPi 网站上供别人下载安装的(*.tar.gz、*.whl)
|
|
20
|
+
|
|
21
|
+
### 2.3 配置文件检查
|
|
22
|
+
```
|
|
23
|
+
python3 setup.py check
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### 2.4 上传前检查
|
|
27
|
+
```
|
|
28
|
+
twine check dist/*
|
|
29
|
+
```
|
|
30
|
+
### 2.4 执行上传
|
|
31
|
+
```
|
|
32
|
+
twine upload dist/*
|
|
33
|
+
```
|
|
34
|
+
### 2.5 清理
|
|
35
|
+
```
|
|
36
|
+
rm -rf build/ dist/ *.egg-info/
|
|
37
|
+
```
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# coding=utf-8
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# coding=utf-8
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# coding=utf-8
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# coding=utf-8
|
|
2
|
+
import datetime
|
|
3
|
+
import hashlib
|
|
4
|
+
import os
|
|
5
|
+
import sys
|
|
6
|
+
import logging
|
|
7
|
+
import better_exceptions
|
|
8
|
+
import pyautogui
|
|
9
|
+
|
|
10
|
+
RECURSIVE_CREATE_DIR = lambda dp: os.makedirs(dp) or dp if not os.path.exists(dp) else dp # ---> mkdir -p
|
|
11
|
+
|
|
12
|
+
def get_current_time():
|
|
13
|
+
return datetime.datetime.now().strftime('%Y-%m-%d_%H_%M_%S')
|
|
14
|
+
|
|
15
|
+
def better_show_exception(print_type="print"):
|
|
16
|
+
"""
|
|
17
|
+
详细打印异常的堆栈信息
|
|
18
|
+
|
|
19
|
+
"""
|
|
20
|
+
e_type, value, e_traceback = sys.exc_info()
|
|
21
|
+
msg = ''
|
|
22
|
+
rst = better_exceptions.format_exception(e_type, value, e_traceback)
|
|
23
|
+
for i in rst:
|
|
24
|
+
msg += i
|
|
25
|
+
msg += '\n'
|
|
26
|
+
if print_type == "print":
|
|
27
|
+
print(msg)
|
|
28
|
+
else:
|
|
29
|
+
logging.error(msg)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def human_duration(seconds: int) -> str:
|
|
33
|
+
"""
|
|
34
|
+
将秒数自动转换成易读字符串
|
|
35
|
+
支持的最大单位是 year,可根据需要扩展
|
|
36
|
+
"""
|
|
37
|
+
if seconds == 0:
|
|
38
|
+
return "0s"
|
|
39
|
+
|
|
40
|
+
# 定义时间单位与秒数的映射(从大到小)
|
|
41
|
+
units = [
|
|
42
|
+
("year", 365 * 24 * 3600),
|
|
43
|
+
("day", 24 * 3600),
|
|
44
|
+
("h", 3600),
|
|
45
|
+
("m", 60),
|
|
46
|
+
("s", 1)
|
|
47
|
+
]
|
|
48
|
+
|
|
49
|
+
parts = []
|
|
50
|
+
remainder = abs(seconds)
|
|
51
|
+
for name, count in units:
|
|
52
|
+
if remainder >= count:
|
|
53
|
+
num = remainder // count
|
|
54
|
+
parts.append(f"{num}{name}")
|
|
55
|
+
remainder -= num * count
|
|
56
|
+
|
|
57
|
+
# 拼接并保留符号
|
|
58
|
+
sign = "-" if seconds < 0 else ""
|
|
59
|
+
return sign + " ".join(parts)
|
|
60
|
+
|
|
61
|
+
def take_screenshot(f_path):
|
|
62
|
+
"""
|
|
63
|
+
截图并保存为文件
|
|
64
|
+
"""
|
|
65
|
+
screenshot = pyautogui.screenshot()
|
|
66
|
+
rst = screenshot.save(f_path)
|
|
67
|
+
return rst
|
|
68
|
+
|
|
69
|
+
def calculate_string_md5(input_string):
|
|
70
|
+
"""
|
|
71
|
+
description: 计算字符串的md5值
|
|
72
|
+
:param input_string:md5
|
|
73
|
+
:return: eg: 098F6BCD4621D373CADE4E832627B4F6
|
|
74
|
+
|
|
75
|
+
"""
|
|
76
|
+
md5 = hashlib.md5()
|
|
77
|
+
b = input_string.encode(encoding='utf-8')
|
|
78
|
+
md5.update(b)
|
|
79
|
+
str_md5 = md5.hexdigest()
|
|
80
|
+
return str_md5
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# coding=utf-8
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
# coding=utf-8
|
|
2
|
+
# -*- coding: utf-8 -*-
|
|
3
|
+
# logger
|
|
4
|
+
import logging
|
|
5
|
+
import logging.config
|
|
6
|
+
import os
|
|
7
|
+
import platform
|
|
8
|
+
import sys
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class Logger:
|
|
12
|
+
if sys.platform.startswith('win'):
|
|
13
|
+
all_log_dir_path = r"D:\log_dir" # 所有日志存储目录路径
|
|
14
|
+
elif sys.platform.startswith('linux'):
|
|
15
|
+
all_log_dir_path = "/var/log/log_dir" # 所有日志存储目录路径
|
|
16
|
+
|
|
17
|
+
def __init__(self,log_name="default"):
|
|
18
|
+
"""
|
|
19
|
+
Logger初始化
|
|
20
|
+
"""
|
|
21
|
+
self.log_name = log_name or "default"
|
|
22
|
+
self.current_logger_dir_path = os.path.join(Logger.all_log_dir_path, self.log_name) # 当前logger的目录路径
|
|
23
|
+
self.root_logger_dir_path = os.path.join(Logger.all_log_dir_path,'root')
|
|
24
|
+
os.makedirs(self.current_logger_dir_path, exist_ok=True)
|
|
25
|
+
os.makedirs(self.root_logger_dir_path, exist_ok=True)
|
|
26
|
+
logging.config.dictConfig(self.get_log_setting()) # load 配置文件
|
|
27
|
+
self.logger = logging.getLogger(log_name)
|
|
28
|
+
|
|
29
|
+
def logger_check(self):
|
|
30
|
+
# ---- 新增以下检查代码 ----
|
|
31
|
+
print(f"当前 logger 名称: {self.logger.name}")
|
|
32
|
+
if self.logger.handlers:
|
|
33
|
+
print("这个 logger 已配置的处理器 (Handlers):")
|
|
34
|
+
for handler in self.logger.handlers:
|
|
35
|
+
print(f" - Handler 类型: {type(handler).__name__}")
|
|
36
|
+
if hasattr(handler, 'formatter') and handler.formatter:
|
|
37
|
+
print(f" 使用的格式器: {handler.formatter._fmt}")
|
|
38
|
+
else:
|
|
39
|
+
print("警告:这个 logger 没有找到任何处理器,可能正在使用上级 logger 的配置!")
|
|
40
|
+
# ---- 检查代码结束 ----
|
|
41
|
+
|
|
42
|
+
def debug(self, message):
|
|
43
|
+
self.logger.debug(message)
|
|
44
|
+
|
|
45
|
+
def info(self, message):
|
|
46
|
+
self.logger.info(message)
|
|
47
|
+
|
|
48
|
+
def warn(self, message):
|
|
49
|
+
self.logger.warning(message)
|
|
50
|
+
|
|
51
|
+
def error(self, message):
|
|
52
|
+
self.logger.error(message)
|
|
53
|
+
|
|
54
|
+
def cri(self, message):
|
|
55
|
+
self.logger.critical(message)
|
|
56
|
+
|
|
57
|
+
def get_log_setting(self):
|
|
58
|
+
setting_map = {
|
|
59
|
+
'version': 1, # 保留字
|
|
60
|
+
'disable_existing_loggers': False, # 禁用已经存在的logger实例,也就是如果为true且有两个logger只会保留最后一个
|
|
61
|
+
# 过滤器
|
|
62
|
+
'filters': {},
|
|
63
|
+
# 日志文件的格式
|
|
64
|
+
'formatters': {
|
|
65
|
+
# 详细的日志格式
|
|
66
|
+
'standard': {
|
|
67
|
+
'format': "[%(asctime)s][%(levelname)s][%(threadName)s:%(thread)d][logger_id:%(name)s][%(filename)s:%(lineno)d] %(message)s"
|
|
68
|
+
},
|
|
69
|
+
# 简单的日志格式
|
|
70
|
+
'simple': {
|
|
71
|
+
'format': '[%(asctime)s][%(levelname)s][%(filename)s:%(lineno)d] %(message)s'
|
|
72
|
+
},
|
|
73
|
+
# 定义一个特殊的日志格式
|
|
74
|
+
'specific': {
|
|
75
|
+
'format': '[%(asctime)s][%(levelname)s][%(message)s]'
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
|
|
79
|
+
# 处理器
|
|
80
|
+
'handlers': {
|
|
81
|
+
|
|
82
|
+
# logger的handlers
|
|
83
|
+
# 终端
|
|
84
|
+
'console': {
|
|
85
|
+
'level': 'INFO',
|
|
86
|
+
'class': 'logging.StreamHandler',
|
|
87
|
+
'formatter': 'standard'
|
|
88
|
+
},
|
|
89
|
+
# INFO
|
|
90
|
+
'info': {
|
|
91
|
+
'level': 'INFO',
|
|
92
|
+
'class': 'logging.handlers.RotatingFileHandler', # 保存到文件,自动切
|
|
93
|
+
'filename': os.path.join(self.current_logger_dir_path,
|
|
94
|
+
"{}_INFO.log".format(self.log_name)),
|
|
95
|
+
'maxBytes': 1024 * 1024 * 50, # 日志大小 50M
|
|
96
|
+
'backupCount': 5, # 最多备份几个
|
|
97
|
+
'formatter': 'standard',
|
|
98
|
+
'encoding': 'utf-8',
|
|
99
|
+
},
|
|
100
|
+
# ERROR
|
|
101
|
+
'error': {
|
|
102
|
+
'level': 'ERROR',
|
|
103
|
+
'class': 'logging.handlers.RotatingFileHandler', # 保存到文件,自动切
|
|
104
|
+
'filename': os.path.join(self.current_logger_dir_path,
|
|
105
|
+
"{}_ERROR.log".format(self.log_name)),
|
|
106
|
+
'maxBytes': 1024 * 1024 * 50, # 日志大小 50M
|
|
107
|
+
'backupCount': 5,
|
|
108
|
+
'formatter': 'standard',
|
|
109
|
+
'encoding': 'utf-8',
|
|
110
|
+
},
|
|
111
|
+
# DEBUG
|
|
112
|
+
'debug': {
|
|
113
|
+
'level': 'DEBUG',
|
|
114
|
+
'class': 'logging.handlers.RotatingFileHandler', # 保存到文件,自动切
|
|
115
|
+
'filename': os.path.join(self.current_logger_dir_path,
|
|
116
|
+
"{}_DEBUG.log".format(self.log_name)),
|
|
117
|
+
'maxBytes': 1024 * 1024 * 50, # 日志大小 50M
|
|
118
|
+
'backupCount': 5,
|
|
119
|
+
'formatter': 'standard',
|
|
120
|
+
'encoding': "utf-8"
|
|
121
|
+
},
|
|
122
|
+
|
|
123
|
+
# root handlers
|
|
124
|
+
# root-终端
|
|
125
|
+
'root_console': {
|
|
126
|
+
'level': 'INFO',
|
|
127
|
+
'class': 'logging.StreamHandler',
|
|
128
|
+
'formatter': 'standard'
|
|
129
|
+
},
|
|
130
|
+
# root-INFO
|
|
131
|
+
'root_info': {
|
|
132
|
+
'level': 'INFO',
|
|
133
|
+
'class': 'logging.handlers.RotatingFileHandler', # 保存到文件,自动切
|
|
134
|
+
'filename': os.path.join(self.root_logger_dir_path,"ROOT_INFO.log"),
|
|
135
|
+
|
|
136
|
+
'maxBytes': 1024 * 1024 * 50, # 日志大小 50M
|
|
137
|
+
'backupCount': 5, # 最多备份几个
|
|
138
|
+
'formatter': 'standard',
|
|
139
|
+
'encoding': 'utf-8',
|
|
140
|
+
},
|
|
141
|
+
# root-ERROR
|
|
142
|
+
'root_error': {
|
|
143
|
+
'level': 'ERROR',
|
|
144
|
+
'class': 'logging.handlers.RotatingFileHandler', # 保存到文件,自动切
|
|
145
|
+
'filename': os.path.join(self.root_logger_dir_path,"ROOT_ERROR.log"),
|
|
146
|
+
|
|
147
|
+
'maxBytes': 1024 * 1024 * 50, # 日志大小 50M
|
|
148
|
+
'backupCount': 5,
|
|
149
|
+
'formatter': 'standard',
|
|
150
|
+
'encoding': 'utf-8',
|
|
151
|
+
},
|
|
152
|
+
# root-DEBUG
|
|
153
|
+
'root_debug': {
|
|
154
|
+
'level': 'DEBUG',
|
|
155
|
+
'class': 'logging.handlers.RotatingFileHandler', # 保存到文件,自动切
|
|
156
|
+
'filename': os.path.join(self.root_logger_dir_path,"ROOT_DEBUG.log"),
|
|
157
|
+
'maxBytes': 1024 * 1024 * 50, # 日志大小 50M
|
|
158
|
+
'backupCount': 5,
|
|
159
|
+
'formatter': 'standard',
|
|
160
|
+
'encoding': "utf-8"
|
|
161
|
+
}
|
|
162
|
+
},
|
|
163
|
+
'loggers': {
|
|
164
|
+
# 默认的logger应用如下配置
|
|
165
|
+
self.log_name: {
|
|
166
|
+
'handlers': ['console', 'info', 'error', 'debug'],
|
|
167
|
+
'level': 'DEBUG',
|
|
168
|
+
'propagate': True, # 向不向更高级别的logger传递,也就是所有logger会向根日志器传递
|
|
169
|
+
},
|
|
170
|
+
|
|
171
|
+
},
|
|
172
|
+
# 新增对根日志器的配置
|
|
173
|
+
'root': {
|
|
174
|
+
'level': 'INFO', # 设置根日志器级别为INFO或更低
|
|
175
|
+
'handlers': ['root_console', 'root_info', 'root_error', 'root_debug'], # 为根日志器添加处理器,例如控制台处理器
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
return setting_map
|
|
179
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# coding=utf-8
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: easy_use_tools
|
|
3
|
+
Version: 1.0.1
|
|
4
|
+
Summary: An easy use tools package
|
|
5
|
+
Home-page: https://github.com/XXX
|
|
6
|
+
Author: yuanyang.li
|
|
7
|
+
Author-email: yuanyang.edison.li@gmail.com
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: Operating System :: OS Independent
|
|
10
|
+
Requires-Python: >=3.8
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Requires-Dist: requests>=2.25.1
|
|
14
|
+
Requires-Dist: numpy>=1.19.5
|
|
15
|
+
Requires-Dist: shortuuid
|
|
16
|
+
Dynamic: author
|
|
17
|
+
Dynamic: author-email
|
|
18
|
+
Dynamic: classifier
|
|
19
|
+
Dynamic: description
|
|
20
|
+
Dynamic: description-content-type
|
|
21
|
+
Dynamic: home-page
|
|
22
|
+
Dynamic: license-file
|
|
23
|
+
Dynamic: requires-dist
|
|
24
|
+
Dynamic: requires-python
|
|
25
|
+
Dynamic: summary
|
|
26
|
+
|
|
27
|
+
# 通用工具集
|
|
28
|
+
这是一个通用工具集, 适用于>=Python3.8
|
|
29
|
+
|
|
30
|
+
## 1. 准备
|
|
31
|
+
### 1.1 安装依赖
|
|
32
|
+
```
|
|
33
|
+
pip3 install --upgrade packaging setuptools wheel twine
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## 2. 命令说明
|
|
37
|
+
### 2.1 本地安装使用
|
|
38
|
+
```
|
|
39
|
+
python setup.py install
|
|
40
|
+
```
|
|
41
|
+
### 2.2 打包
|
|
42
|
+
```
|
|
43
|
+
python setup.py sdist bdist_wheel
|
|
44
|
+
```
|
|
45
|
+
在当前dist目录下的两个文件是要上传到 PyPi 网站上供别人下载安装的(*.tar.gz、*.whl)
|
|
46
|
+
|
|
47
|
+
### 2.3 配置文件检查
|
|
48
|
+
```
|
|
49
|
+
python3 setup.py check
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### 2.4 上传前检查
|
|
53
|
+
```
|
|
54
|
+
twine check dist/*
|
|
55
|
+
```
|
|
56
|
+
### 2.4 执行上传
|
|
57
|
+
```
|
|
58
|
+
twine upload dist/*
|
|
59
|
+
```
|
|
60
|
+
### 2.5 清理
|
|
61
|
+
```
|
|
62
|
+
rm -rf build/ dist/ *.egg-info/
|
|
63
|
+
```
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
setup.py
|
|
4
|
+
easy_use_tools/__init__.py
|
|
5
|
+
easy_use_tools/manage.py
|
|
6
|
+
easy_use_tools.egg-info/PKG-INFO
|
|
7
|
+
easy_use_tools.egg-info/SOURCES.txt
|
|
8
|
+
easy_use_tools.egg-info/dependency_links.txt
|
|
9
|
+
easy_use_tools.egg-info/entry_points.txt
|
|
10
|
+
easy_use_tools.egg-info/requires.txt
|
|
11
|
+
easy_use_tools.egg-info/top_level.txt
|
|
12
|
+
easy_use_tools/core/__init__.py
|
|
13
|
+
easy_use_tools/utils/__init__.py
|
|
14
|
+
easy_use_tools/utils/common.py
|
|
15
|
+
easy_use_tools/utils/log.py
|
|
16
|
+
easy_use_tools/utils/linux/__init__.py
|
|
17
|
+
easy_use_tools/utils/windows/__init__.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
easy_use_tools
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# coding=utf-8
|
|
2
|
+
import setuptools # 导入setuptools打包工具
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
def parse_requirements(filename):
|
|
6
|
+
"""使用 packaging 包安全地解析 requirements.txt"""
|
|
7
|
+
try:
|
|
8
|
+
from packaging.requirements import Requirement
|
|
9
|
+
except ImportError:
|
|
10
|
+
# 回退方案:如果packaging不可用,尝试简单处理
|
|
11
|
+
return simple_parse_requirements(filename)
|
|
12
|
+
|
|
13
|
+
requirements = []
|
|
14
|
+
file_path = Path(filename)
|
|
15
|
+
|
|
16
|
+
if not file_path.exists():
|
|
17
|
+
return requirements
|
|
18
|
+
|
|
19
|
+
with open(file_path, 'r', encoding='utf-8') as f:
|
|
20
|
+
for line in f:
|
|
21
|
+
line = line.strip()
|
|
22
|
+
# 跳过空行和注释
|
|
23
|
+
if not line or line.startswith('#'):
|
|
24
|
+
continue
|
|
25
|
+
try:
|
|
26
|
+
# 使用packaging验证并规范化需求字符串
|
|
27
|
+
req = Requirement(line)
|
|
28
|
+
requirements.append(str(req))
|
|
29
|
+
except Exception:
|
|
30
|
+
# 如果解析失败,回退到原始行
|
|
31
|
+
requirements.append(line)
|
|
32
|
+
|
|
33
|
+
return requirements
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def simple_parse_requirements(filename):
|
|
37
|
+
"""简化的解析器,作为回退方案"""
|
|
38
|
+
file_path = Path(filename)
|
|
39
|
+
if not file_path.exists():
|
|
40
|
+
return []
|
|
41
|
+
|
|
42
|
+
with open(file_path, 'r', encoding='utf-8') as f:
|
|
43
|
+
return [
|
|
44
|
+
line.strip() for line in f
|
|
45
|
+
if line.strip() and not line.startswith('#')
|
|
46
|
+
]
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
with open("README.md", "r", encoding="utf-8") as fh:
|
|
50
|
+
long_description = fh.read()
|
|
51
|
+
|
|
52
|
+
setuptools.setup(
|
|
53
|
+
name="easy_use_tools", # 用自己的名替换其中的YOUR_USERNAME_
|
|
54
|
+
version="1.0.1", # 包版本号,便于维护版本,保证每次发布都是版本都是唯一的
|
|
55
|
+
author="yuanyang.li", # 作者,可以写自己的姓名
|
|
56
|
+
author_email="yuanyang.edison.li@gmail.com", # 作者联系方式,可写自己的邮箱地址
|
|
57
|
+
description="An easy use tools package", # 包的简述
|
|
58
|
+
long_description=long_description, # 包的详细介绍,一般在README.md文件内
|
|
59
|
+
long_description_content_type="text/markdown",
|
|
60
|
+
url="https://github.com/XXX", # 自己项目地址,比如github的项目地址
|
|
61
|
+
license_files=['LICENSE'],
|
|
62
|
+
packages=setuptools.find_packages(),
|
|
63
|
+
# 依赖管理
|
|
64
|
+
install_requires=parse_requirements('requirements'),
|
|
65
|
+
# install_requires=[ # 项目运行所依赖的第三方包列表
|
|
66
|
+
# "requests >= 2.25.1", # 可以指定版本
|
|
67
|
+
# "shortuuid", # 也可以不指定版本,但建议指定
|
|
68
|
+
# "PyYAML >= 5.4.1",
|
|
69
|
+
# # 注意:通常不推荐使用"pandas"这样宽泛的声明,最好指明最低版本
|
|
70
|
+
# ],
|
|
71
|
+
entry_points={
|
|
72
|
+
"console_scripts" : ['show_info = easy_use_tools.manage:run']
|
|
73
|
+
}, #安装成功后,在命令行输入show_infot easy_use_tools.manage.py中的run了, 格式:'命令名=包.模块:函数'
|
|
74
|
+
classifiers=[
|
|
75
|
+
"Programming Language :: Python :: 3",
|
|
76
|
+
"Operating System :: OS Independent",
|
|
77
|
+
],
|
|
78
|
+
python_requires='>=3.8', # 对python的最低版本要求
|
|
79
|
+
)
|