lkd-pro 0.2.0__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.
- lkd_pro-0.2.0/PKG-INFO +644 -0
- lkd_pro-0.2.0/README.md +607 -0
- lkd_pro-0.2.0/lkd/__init__.py +39 -0
- lkd_pro-0.2.0/lkd/api/__init__.py +68 -0
- lkd_pro-0.2.0/lkd/api/api.py +889 -0
- lkd_pro-0.2.0/lkd/cache/__init__.py +9 -0
- lkd_pro-0.2.0/lkd/cache/local_cache.py +173 -0
- lkd_pro-0.2.0/lkd/client/__init__.py +25 -0
- lkd_pro-0.2.0/lkd/client/client.py +201 -0
- lkd_pro-0.2.0/lkd/client/request_base.py +93 -0
- lkd_pro-0.2.0/lkd/client/request_delete.py +9 -0
- lkd_pro-0.2.0/lkd/client/request_params.py +9 -0
- lkd_pro-0.2.0/lkd/client/request_patch.py +9 -0
- lkd_pro-0.2.0/lkd/client/request_post.py +9 -0
- lkd_pro-0.2.0/lkd/client/request_put.py +9 -0
- lkd_pro-0.2.0/lkd/env/__init__.py +9 -0
- lkd_pro-0.2.0/lkd/env/auto_client.py +325 -0
- lkd_pro-0.2.0/lkd/env/device_info.py +160 -0
- lkd_pro-0.2.0/lkd/human/__init__.py +0 -0
- lkd_pro-0.2.0/lkd/human/human.py +740 -0
- lkd_pro-0.2.0/lkd/logs/__init__.py +132 -0
- lkd_pro-0.2.0/lkd/logs/err_logs.py +137 -0
- lkd_pro-0.2.0/lkd/mwin/__init__.py +0 -0
- lkd_pro-0.2.0/lkd/mwin/find_image.py +310 -0
- lkd_pro-0.2.0/lkd/mwin/mbot.py +1140 -0
- lkd_pro-0.2.0/lkd/py.typed +0 -0
- lkd_pro-0.2.0/lkd/settings/__init__.py +10 -0
- lkd_pro-0.2.0/lkd/settings/initialization.py +140 -0
- lkd_pro-0.2.0/lkd/settings/settings.py +138 -0
- lkd_pro-0.2.0/lkd/util/__init__.py +0 -0
- lkd_pro-0.2.0/lkd/util/file/__init__.py +0 -0
- lkd_pro-0.2.0/lkd/util/file/file.py +211 -0
- lkd_pro-0.2.0/lkd/util/file/folder.py +117 -0
- lkd_pro-0.2.0/lkd/util/file/mjson.py +48 -0
- lkd_pro-0.2.0/lkd/util/file/path.py +247 -0
- lkd_pro-0.2.0/lkd/util/network.py +79 -0
- lkd_pro-0.2.0/lkd/util/up_c.py +736 -0
- lkd_pro-0.2.0/lkd/util/util.py +598 -0
- lkd_pro-0.2.0/lkd/var/__init__.py +9 -0
- lkd_pro-0.2.0/lkd/var/variables.py +48 -0
- lkd_pro-0.2.0/lkd_pro.egg-info/PKG-INFO +644 -0
- lkd_pro-0.2.0/lkd_pro.egg-info/SOURCES.txt +46 -0
- lkd_pro-0.2.0/lkd_pro.egg-info/dependency_links.txt +1 -0
- lkd_pro-0.2.0/lkd_pro.egg-info/not-zip-safe +1 -0
- lkd_pro-0.2.0/lkd_pro.egg-info/requires.txt +9 -0
- lkd_pro-0.2.0/lkd_pro.egg-info/top_level.txt +1 -0
- lkd_pro-0.2.0/setup.cfg +4 -0
- lkd_pro-0.2.0/setup.py +55 -0
lkd_pro-0.2.0/PKG-INFO
ADDED
|
@@ -0,0 +1,644 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: lkd_pro
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: 自动注册和认证
|
|
5
|
+
Home-page: https://github.com/songhang/lkddb_pro
|
|
6
|
+
Author: songhang
|
|
7
|
+
Author-email: 1026536804@qq.com
|
|
8
|
+
Classifier: Development Status :: 4 - Beta
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Requires-Python: >=3.8
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
Requires-Dist: pywin32>=311
|
|
20
|
+
Requires-Dist: Pillow>=10.0.0
|
|
21
|
+
Requires-Dist: requests>=2.32.0
|
|
22
|
+
Requires-Dist: cachetools>=5.0.0
|
|
23
|
+
Requires-Dist: pandas>=2.0.0
|
|
24
|
+
Requires-Dist: openpyxl>=3.1.0
|
|
25
|
+
Requires-Dist: psutil>=5.9.0
|
|
26
|
+
Requires-Dist: opencv-python>=4.8.0
|
|
27
|
+
Requires-Dist: pydirectinput>=1.0.4
|
|
28
|
+
Dynamic: author
|
|
29
|
+
Dynamic: author-email
|
|
30
|
+
Dynamic: classifier
|
|
31
|
+
Dynamic: description
|
|
32
|
+
Dynamic: description-content-type
|
|
33
|
+
Dynamic: home-page
|
|
34
|
+
Dynamic: requires-dist
|
|
35
|
+
Dynamic: requires-python
|
|
36
|
+
Dynamic: summary
|
|
37
|
+
|
|
38
|
+
# LKD Python SDK
|
|
39
|
+
|
|
40
|
+
[](https://pypi.org/project/lkd/)
|
|
41
|
+
[](https://www.python.org/downloads/)
|
|
42
|
+
[](LICENSE)
|
|
43
|
+
|
|
44
|
+
## 📖 项目简介
|
|
45
|
+
|
|
46
|
+
LKD 是电商商品数据处理与自动化上传系统。提供 Excel 表格与图片批量匹配、数据清洗、API 上传、错误日志异步上报等一站式解决方案,帮助电商企业高效管理商品数据。
|
|
47
|
+
|
|
48
|
+
### 核心特性
|
|
49
|
+
|
|
50
|
+
- 🔐 **自动认证**: Token 自动刷新、设备心跳维护
|
|
51
|
+
- 💾 **本地缓存**: 内存 + 文件双重缓存,支持持久化存储
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## 📦 快速开始
|
|
56
|
+
|
|
57
|
+
### 1. 安装依赖
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
pip install -r requirements.txt
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
或使用 pip 安装(如已发布):
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
pip install lkd
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### 2. 初始化配置
|
|
70
|
+
|
|
71
|
+
在使用 LKD 模块前,需要先初始化全局变量和 IP 配置:
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
from lkd.var.variables import glv
|
|
75
|
+
from lkd.settings.initialization import default as init_default
|
|
76
|
+
|
|
77
|
+
# 设置服务器 IP(必须在最前面)
|
|
78
|
+
glv.set("LOCAL_IP", "192.168.2.28:8000") # 本地服务器
|
|
79
|
+
# glv.set("REMOTE_IP", "your.remote.ip") # 远程服务器(可选)
|
|
80
|
+
|
|
81
|
+
# 执行完整初始化流程
|
|
82
|
+
success = init_default()
|
|
83
|
+
if success:
|
|
84
|
+
print("LKD 初始化完成")
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### 3. 使用示例
|
|
88
|
+
|
|
89
|
+
#### 用户认证
|
|
90
|
+
|
|
91
|
+
```python
|
|
92
|
+
from lkd.api import login, register
|
|
93
|
+
|
|
94
|
+
# 登录(密码默认使用设备 ID 后 6 位)
|
|
95
|
+
result = login("your_password")
|
|
96
|
+
if result["success"]:
|
|
97
|
+
print("登录成功")
|
|
98
|
+
access_token = result["data"]["access_token"]
|
|
99
|
+
else:
|
|
100
|
+
# 登录失败可尝试注册
|
|
101
|
+
register_result = register("your_password")
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
#### 商品上传
|
|
105
|
+
|
|
106
|
+
```python
|
|
107
|
+
from lkd.api import send_products
|
|
108
|
+
|
|
109
|
+
product_data = {
|
|
110
|
+
"title": "商品名称",
|
|
111
|
+
"price": 99.99,
|
|
112
|
+
"stock": 100,
|
|
113
|
+
"shop_id": "shop_001",
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
result = send_products(product_data)
|
|
117
|
+
if result["success"]:
|
|
118
|
+
print("商品上传成功")
|
|
119
|
+
else:
|
|
120
|
+
print(f"上传失败:{result['error']}")
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
#### 获取任务列表
|
|
124
|
+
|
|
125
|
+
```python
|
|
126
|
+
from lkd.api import get_task
|
|
127
|
+
|
|
128
|
+
result = get_task(status="pending", limit=10)
|
|
129
|
+
if result["success"]:
|
|
130
|
+
tasks = result["data"]["tasks"]
|
|
131
|
+
for task in tasks:
|
|
132
|
+
print(f"任务 ID: {task['id']}, 状态:{task['status']}")
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
#### 错误日志上报
|
|
136
|
+
|
|
137
|
+
```python
|
|
138
|
+
from lkd.logs.err_logs import send_logs
|
|
139
|
+
|
|
140
|
+
send_logs(
|
|
141
|
+
task="task_001",
|
|
142
|
+
error_message="商品上传失败:库存不足",
|
|
143
|
+
screenshot_path="error.png"
|
|
144
|
+
)
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
#### 发送设备心跳
|
|
148
|
+
|
|
149
|
+
```python
|
|
150
|
+
from lkd.api import send_heartbeat
|
|
151
|
+
import datetime
|
|
152
|
+
|
|
153
|
+
start_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
|
154
|
+
result = send_heartbeat(
|
|
155
|
+
start_heartbeat=start_time,
|
|
156
|
+
access_token="your_access_token",
|
|
157
|
+
ref_token="your_refresh_token",
|
|
158
|
+
status=1 # 1=空闲,2=工作中
|
|
159
|
+
)
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## 📁 目录结构
|
|
165
|
+
|
|
166
|
+
```
|
|
167
|
+
lkd/
|
|
168
|
+
├── api/ # API 接口与数据上传
|
|
169
|
+
│ ├── __init__.py
|
|
170
|
+
│ └── api.py # 所有 API 接口封装
|
|
171
|
+
├── cache/ # 缓存管理
|
|
172
|
+
│ ├── __init__.py
|
|
173
|
+
│ └── local_cache.py # 本地缓存与文件缓存
|
|
174
|
+
├── client/ # HTTP 客户端
|
|
175
|
+
│ ├── __init__.py
|
|
176
|
+
│ ├── client.py # 请求客户端 (CPRequest)
|
|
177
|
+
│ └── request_*.py # 请求对象封装 (BaseRequest 子类)
|
|
178
|
+
├── env/ # 环境与设备信息
|
|
179
|
+
│ ├── __init__.py
|
|
180
|
+
│ └── device_info.py # 设备唯一标识生成
|
|
181
|
+
├── human/ # 人工交互工具
|
|
182
|
+
├── logs/ # 日志系统
|
|
183
|
+
│ ├── __init__.py # 日志配置
|
|
184
|
+
│ └── err_logs.py # 错误日志上报
|
|
185
|
+
├── mwin/ # Windows 自动化
|
|
186
|
+
├── settings/ # 配置管理
|
|
187
|
+
│ ├── __init__.py
|
|
188
|
+
│ ├── settings.py # 系统配置 (单例模式)
|
|
189
|
+
│ └── initialization.py # 初始化流程
|
|
190
|
+
├── util/ # 通用工具
|
|
191
|
+
│ ├── file/ # 文件操作工具
|
|
192
|
+
│ │ ├── file.py # 文件管理
|
|
193
|
+
│ │ ├── folder.py # 文件夹管理
|
|
194
|
+
│ │ └── path.py # 路径管理
|
|
195
|
+
│ └── up_c.py # Excel 上传主流程
|
|
196
|
+
├── var/ # 全局变量管理
|
|
197
|
+
│ └── variables.py # GlobalVariables 单例
|
|
198
|
+
├── __init__.py # 包入口
|
|
199
|
+
└── test.py # 测试与初始化工具
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
204
|
+
## 🔧 架构规范
|
|
205
|
+
|
|
206
|
+
### 设计模式
|
|
207
|
+
|
|
208
|
+
#### 单例模式
|
|
209
|
+
|
|
210
|
+
核心模块必须使用单例模式,确保全局唯一实例:
|
|
211
|
+
|
|
212
|
+
- `Settings` - 系统配置管理器
|
|
213
|
+
- `GlobalVariables` - 全局变量管理器
|
|
214
|
+
- `CacheManager` - 缓存管理器
|
|
215
|
+
- `DeviceInfo` - 设备信息生成器
|
|
216
|
+
|
|
217
|
+
```python
|
|
218
|
+
# Settings 使用示例
|
|
219
|
+
from lkd.settings import get_settings
|
|
220
|
+
|
|
221
|
+
settings = get_settings() # 始终返回同一实例
|
|
222
|
+
host_url = settings.host_url
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
#### 延迟导入
|
|
226
|
+
|
|
227
|
+
解决循环依赖问题,在方法内部动态导入:
|
|
228
|
+
|
|
229
|
+
```python
|
|
230
|
+
def _get_api_module():
|
|
231
|
+
"""延迟导入 API 模块,避免循环依赖"""
|
|
232
|
+
from lkd.api import api
|
|
233
|
+
return api
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
### 代码规范
|
|
237
|
+
|
|
238
|
+
#### 类型注解
|
|
239
|
+
|
|
240
|
+
所有公共 API 必须包含完整的类型注解:
|
|
241
|
+
|
|
242
|
+
```python
|
|
243
|
+
from typing import Dict, Any, Optional
|
|
244
|
+
|
|
245
|
+
def login(password: str) -> Dict[str, Any]:
|
|
246
|
+
"""
|
|
247
|
+
用户登录
|
|
248
|
+
|
|
249
|
+
Args:
|
|
250
|
+
password: 用户密码
|
|
251
|
+
|
|
252
|
+
Returns:
|
|
253
|
+
登录结果字典
|
|
254
|
+
"""
|
|
255
|
+
pass
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
#### 请求类继承
|
|
259
|
+
|
|
260
|
+
所有 HTTP 请求类必须继承自 `BaseRequest` 抽象基类:
|
|
261
|
+
|
|
262
|
+
```python
|
|
263
|
+
from lkd.client.request_base import BaseRequest
|
|
264
|
+
|
|
265
|
+
class RequestPost(BaseRequest):
|
|
266
|
+
def __init__(self, request_url: str) -> None:
|
|
267
|
+
super().__init__(method="POST", request_url=request_url)
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
### 安全规范
|
|
271
|
+
|
|
272
|
+
#### 线程安全
|
|
273
|
+
|
|
274
|
+
共享状态访问必须加锁:
|
|
275
|
+
|
|
276
|
+
```python
|
|
277
|
+
import threading
|
|
278
|
+
|
|
279
|
+
class CacheManager:
|
|
280
|
+
def __init__(self) -> None:
|
|
281
|
+
self._cache: Dict[str, Any] = {}
|
|
282
|
+
self._lock = threading.Lock()
|
|
283
|
+
|
|
284
|
+
def set(self, key: str, value: Any) -> None:
|
|
285
|
+
with self._lock:
|
|
286
|
+
self._cache[key] = value
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
#### 上下文管理器
|
|
290
|
+
|
|
291
|
+
文件/网络操作必须使用上下文管理器:
|
|
292
|
+
|
|
293
|
+
```python
|
|
294
|
+
def read_file(path: str) -> Optional[str]:
|
|
295
|
+
try:
|
|
296
|
+
with open(path, "r", encoding="utf-8") as f:
|
|
297
|
+
return f.read()
|
|
298
|
+
except Exception as e:
|
|
299
|
+
log_error(f"读取文件失败:{e}")
|
|
300
|
+
return None
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
### 容错机制
|
|
304
|
+
|
|
305
|
+
#### 多级降级策略
|
|
306
|
+
|
|
307
|
+
密码初始化等关键流程必须实现多级降级:
|
|
308
|
+
|
|
309
|
+
```python
|
|
310
|
+
def _init_password(self) -> None:
|
|
311
|
+
# 优先使用设备 ID 生成的密码
|
|
312
|
+
device_pwd = _get_pwd_from_device()
|
|
313
|
+
if device_pwd:
|
|
314
|
+
self._password = device_pwd
|
|
315
|
+
return
|
|
316
|
+
|
|
317
|
+
# 尝试从缓存获取
|
|
318
|
+
cached_pwd = CACHE.get("pwd", "")
|
|
319
|
+
if cached_pwd:
|
|
320
|
+
self._password = cached_pwd
|
|
321
|
+
return
|
|
322
|
+
|
|
323
|
+
# 生成新密码并保存
|
|
324
|
+
self._password = random_pwd()
|
|
325
|
+
CACHE["pwd"] = self._password
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
#### 异常处理
|
|
329
|
+
|
|
330
|
+
认证/注册/心跳流程必须包裹在 try-except 块中:
|
|
331
|
+
|
|
332
|
+
```python
|
|
333
|
+
try:
|
|
334
|
+
result = api_client.send_heartbeat(...)
|
|
335
|
+
if result["success"]:
|
|
336
|
+
log_print("心跳发送成功")
|
|
337
|
+
except Exception as e:
|
|
338
|
+
log_error(f"心跳发送异常:{e}")
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
### 路径规范
|
|
342
|
+
|
|
343
|
+
文件路径获取必须实现多层降级策略:
|
|
344
|
+
|
|
345
|
+
```python
|
|
346
|
+
def get_documents_path(self) -> str:
|
|
347
|
+
"""获取文档路径(带降级策略)"""
|
|
348
|
+
try:
|
|
349
|
+
# 尝试访问 Documents 目录
|
|
350
|
+
path = get_known_folder_path("Documents")
|
|
351
|
+
if path:
|
|
352
|
+
return os.path.join(path, "0_mt")
|
|
353
|
+
except Exception:
|
|
354
|
+
pass
|
|
355
|
+
|
|
356
|
+
try:
|
|
357
|
+
# 降级到 APPDATA
|
|
358
|
+
path = os.getenv("APPDATA")
|
|
359
|
+
if path:
|
|
360
|
+
return os.path.join(path, "0_mt")
|
|
361
|
+
except Exception:
|
|
362
|
+
pass
|
|
363
|
+
|
|
364
|
+
# 最终降级到临时目录
|
|
365
|
+
return tempfile.gettempdir()
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
### 配置加载规范
|
|
369
|
+
|
|
370
|
+
`Settings.host_url` 必须实现动态检查机制,每次访问时自动从 `glv` 重新读取 IP 配置:
|
|
371
|
+
|
|
372
|
+
```python
|
|
373
|
+
@property
|
|
374
|
+
def host_url(self) -> str:
|
|
375
|
+
"""API 主机 URL(动态获取)"""
|
|
376
|
+
# 如果当前 host_url 为空,尝试重新从 glv 加载
|
|
377
|
+
if not self._host_url:
|
|
378
|
+
self._local_ip = glv.get("LOCAL_IP", "")
|
|
379
|
+
self._remote_ip = glv.get("REMOTE_IP", "")
|
|
380
|
+
self._host_url = self._build_host_url()
|
|
381
|
+
return self._host_url
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
---
|
|
385
|
+
|
|
386
|
+
## 📚 主要模块说明
|
|
387
|
+
|
|
388
|
+
### API 模块 (`lkd.api`)
|
|
389
|
+
|
|
390
|
+
提供完整的后端 API 接口封装:
|
|
391
|
+
|
|
392
|
+
#### 认证相关
|
|
393
|
+
|
|
394
|
+
- `register(password: str)` - 用户注册
|
|
395
|
+
- `login(password: str)` - 用户登录
|
|
396
|
+
- `refresh_token(ref_token: str, app_name: str)` - 刷新 Token
|
|
397
|
+
|
|
398
|
+
#### 设备管理
|
|
399
|
+
|
|
400
|
+
- `register_device(access_token, ref_token, **kwargs)` - 注册或更新设备
|
|
401
|
+
- `send_heartbeat(start_heartbeat, access_token, ref_token, status, **kwargs)` - 发送心跳
|
|
402
|
+
|
|
403
|
+
#### 任务管理
|
|
404
|
+
|
|
405
|
+
- `get_task(**kwargs)` - 获取任务列表
|
|
406
|
+
- `update_task(id, **kwargs)` - 更新任务
|
|
407
|
+
- `logs(task_id, log_content, screenshot)` - 发送任务日志
|
|
408
|
+
|
|
409
|
+
#### 商品管理
|
|
410
|
+
|
|
411
|
+
- `send_products(data)` - 发送商品信息
|
|
412
|
+
- `get_products(**kwargs)` - 查询商品信息
|
|
413
|
+
|
|
414
|
+
#### 店铺管理
|
|
415
|
+
|
|
416
|
+
- `get_shop(shop_id, **kwargs)` - 获取店铺信息
|
|
417
|
+
- `update_shop(shop_id, **kwargs)` - 更新店铺信息
|
|
418
|
+
- `get_second_categories(**kwargs)` - 获取二级类目
|
|
419
|
+
- `create_or_update_second(**kwargs)` - 创建/更新二级类目
|
|
420
|
+
|
|
421
|
+
#### 采购管理
|
|
422
|
+
|
|
423
|
+
- `get_purchase(**kwargs)` - 获取拼多多采购信息
|
|
424
|
+
- `post_purchase(**kwargs)` - 采购 PDD 商品
|
|
425
|
+
- `put_purchase(**kwargs)` - 更新采购信息
|
|
426
|
+
|
|
427
|
+
#### 绑定关系
|
|
428
|
+
|
|
429
|
+
- `query_pdd_bind_products(**kwargs)` - 查询商品绑定关系
|
|
430
|
+
- `update_pdd_bind_product(id, **kwargs)` - 更新绑定关系
|
|
431
|
+
|
|
432
|
+
### 缓存模块 (`lkd.cache`)
|
|
433
|
+
|
|
434
|
+
```python
|
|
435
|
+
from lkd.cache import CACHE, FileCache
|
|
436
|
+
|
|
437
|
+
# 内存缓存(字典式访问)
|
|
438
|
+
CACHE["key"] = "value"
|
|
439
|
+
value = CACHE["key"]
|
|
440
|
+
|
|
441
|
+
# 或使用标准方法
|
|
442
|
+
CACHE.set("key", "value")
|
|
443
|
+
value = CACHE.get("key")
|
|
444
|
+
|
|
445
|
+
# 文件缓存(持久化)
|
|
446
|
+
file_cache = FileCache("/path/to/cache")
|
|
447
|
+
file_cache.start_background_save() # 启动后台自动保存
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
### 日志模块 (`lkd.logs`)
|
|
451
|
+
|
|
452
|
+
```python
|
|
453
|
+
from lkd.logs import log_print, log_error, log_warning, set_log_dir
|
|
454
|
+
|
|
455
|
+
# 设置日志目录
|
|
456
|
+
set_log_dir("/path/to/logs")
|
|
457
|
+
|
|
458
|
+
# 记录日志
|
|
459
|
+
log_print("普通信息") # INFO 级别
|
|
460
|
+
log_error("错误信息") # ERROR 级别
|
|
461
|
+
log_warning("警告信息") # WARNING 级别
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
### 全局变量模块 (`lkd.var`)
|
|
465
|
+
|
|
466
|
+
```python
|
|
467
|
+
from lkd.var.variables import glv
|
|
468
|
+
|
|
469
|
+
# 设置变量
|
|
470
|
+
glv.set("LOCAL_IP", "192.168.2.28:8000")
|
|
471
|
+
glv.set("gvar_task_path", "/path/to/tasks")
|
|
472
|
+
|
|
473
|
+
# 获取变量
|
|
474
|
+
local_ip = glv.get("LOCAL_IP")
|
|
475
|
+
task_path = glv.get("gvar_task_path")
|
|
476
|
+
|
|
477
|
+
# 检查是否存在
|
|
478
|
+
if glv.has("LOCAL_IP"):
|
|
479
|
+
print("IP 已配置")
|
|
480
|
+
```
|
|
481
|
+
|
|
482
|
+
---
|
|
483
|
+
|
|
484
|
+
## ⚙️ 配置说明
|
|
485
|
+
|
|
486
|
+
### IP 配置
|
|
487
|
+
|
|
488
|
+
```python
|
|
489
|
+
from lkd.var.variables import glv
|
|
490
|
+
|
|
491
|
+
# 本地服务器(优先使用)
|
|
492
|
+
glv.set("LOCAL_IP", "192.168.2.28:8000")
|
|
493
|
+
|
|
494
|
+
# 远程服务器(备用)
|
|
495
|
+
glv.set("REMOTE_IP", "your.remote.ip:port")
|
|
496
|
+
|
|
497
|
+
# Settings 会自动选择 LOCAL_IP(如果存在),否则使用 REMOTE_IP
|
|
498
|
+
# 并构建完整的 URL: http://{ip}/api
|
|
499
|
+
```
|
|
500
|
+
|
|
501
|
+
### 路径配置
|
|
502
|
+
|
|
503
|
+
```python
|
|
504
|
+
from lkd.var.variables import glv
|
|
505
|
+
|
|
506
|
+
# 配置关键路径
|
|
507
|
+
glv.set("gvar_config_path", "/path/to/config")
|
|
508
|
+
glv.set("gvar_task_path", "/path/to/tasks")
|
|
509
|
+
glv.set("gvar_img_path", "/path/to/images")
|
|
510
|
+
glv.set("gvar_logs_path", "/path/to/logs")
|
|
511
|
+
glv.set("gvar_export_path", "/path/to/export")
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
### 自动认证客户端
|
|
515
|
+
|
|
516
|
+
```python
|
|
517
|
+
from lkd.env.auto_client import AutoClient
|
|
518
|
+
|
|
519
|
+
# 创建自动连接客户端
|
|
520
|
+
auto_client = AutoClient(app_name="solider")
|
|
521
|
+
|
|
522
|
+
# 启动心跳
|
|
523
|
+
auto_client.run()
|
|
524
|
+
|
|
525
|
+
# 客户端会自动处理:
|
|
526
|
+
# 1. Token 检查和刷新
|
|
527
|
+
# 2. 登录/注册
|
|
528
|
+
# 3. 设备注册
|
|
529
|
+
# 4. 定时心跳发送
|
|
530
|
+
```
|
|
531
|
+
|
|
532
|
+
---
|
|
533
|
+
|
|
534
|
+
## ⚠️ 注意事项
|
|
535
|
+
|
|
536
|
+
1. **初始化顺序**: 必须先设置 IP 配置 (`LOCAL_IP`/`REMOTE_IP`),再执行其他操作
|
|
537
|
+
2. **Excel 格式规范**: 确保 Excel 表格格式规范,列名与配置一致
|
|
538
|
+
3. **图片命名**: 图片文件夹命名需与 Excel 表格对应
|
|
539
|
+
4. **权限要求**: Windows 自动化功能需要相应系统权限
|
|
540
|
+
5. **Python 版本**: 需要 Python 3.8 或更高版本
|
|
541
|
+
6. **线程安全**: 多线程环境下请使用锁机制保护共享状态
|
|
542
|
+
|
|
543
|
+
---
|
|
544
|
+
|
|
545
|
+
## 🔍 常见问题
|
|
546
|
+
|
|
547
|
+
### Q: 如何修改 API 服务器地址?
|
|
548
|
+
|
|
549
|
+
A: 通过全局变量配置(必须在初始化前设置):
|
|
550
|
+
|
|
551
|
+
```python
|
|
552
|
+
from lkd.var.variables import glv
|
|
553
|
+
glv.set("LOCAL_IP", "new.server.ip:port")
|
|
554
|
+
```
|
|
555
|
+
|
|
556
|
+
### Q: 日志文件在哪里?
|
|
557
|
+
|
|
558
|
+
A: 默认位于初始化时配置的 `gvar_logs_path` 目录,可通过 `set_log_dir()` 自定义。
|
|
559
|
+
|
|
560
|
+
### Q: 如何处理大量商品上传?
|
|
561
|
+
|
|
562
|
+
A: 使用 `ExcelUploader` 类,支持并发上传:
|
|
563
|
+
|
|
564
|
+
```python
|
|
565
|
+
from lkd.util.up_c import ExcelUploader
|
|
566
|
+
|
|
567
|
+
uploader = ExcelUploader(
|
|
568
|
+
excel_path="products.xlsx",
|
|
569
|
+
shop_name="店铺名称",
|
|
570
|
+
max_workers=10 # 并发数
|
|
571
|
+
)
|
|
572
|
+
uploader.run()
|
|
573
|
+
```
|
|
574
|
+
|
|
575
|
+
### Q: Token 过期了怎么办?
|
|
576
|
+
|
|
577
|
+
A: 使用 `AutoClient` 会自动处理 Token 刷新。手动刷新可使用:
|
|
578
|
+
|
|
579
|
+
```python
|
|
580
|
+
from lkd.api import refresh_token
|
|
581
|
+
|
|
582
|
+
result = refresh_token(
|
|
583
|
+
ref_token="your_refresh_token",
|
|
584
|
+
app_name="solider"
|
|
585
|
+
)
|
|
586
|
+
```
|
|
587
|
+
|
|
588
|
+
### Q: 设备心跳如何发送?
|
|
589
|
+
|
|
590
|
+
A: 推荐使用 `AutoClient` 自动发送,或手动调用:
|
|
591
|
+
|
|
592
|
+
```python
|
|
593
|
+
from lkd.api import send_heartbeat
|
|
594
|
+
import datetime
|
|
595
|
+
|
|
596
|
+
result = send_heartbeat(
|
|
597
|
+
start_heartbeat=datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
|
|
598
|
+
access_token="your_access_token",
|
|
599
|
+
ref_token="your_refresh_token",
|
|
600
|
+
status=1
|
|
601
|
+
)
|
|
602
|
+
```
|
|
603
|
+
|
|
604
|
+
---
|
|
605
|
+
|
|
606
|
+
## 📝 更新日志
|
|
607
|
+
|
|
608
|
+
详见 [CHANGELOG.md](CHANGELOG.md) 和 [版本日志.txt](版本日志.txt)
|
|
609
|
+
|
|
610
|
+
### v0.2.0 (2026-04-02)
|
|
611
|
+
|
|
612
|
+
- ✅ 修复 Settings 动态加载 IP 配置问题
|
|
613
|
+
- ✅ 优化心跳 URL 拼接逻辑
|
|
614
|
+
- ✅ 增强缓存模块线程安全性
|
|
615
|
+
- ✅ 改进路径降级策略
|
|
616
|
+
|
|
617
|
+
---
|
|
618
|
+
|
|
619
|
+
## 🤝 贡献指南
|
|
620
|
+
|
|
621
|
+
欢迎提交 Issue 和 Pull Request!贡献代码请遵循以下规范:
|
|
622
|
+
|
|
623
|
+
1. 所有公共 API 必须包含完整 docstring
|
|
624
|
+
2. 保持类型注解风格一致
|
|
625
|
+
3. 关键流程必须包含异常处理
|
|
626
|
+
4. 新增功能需补充测试用例
|
|
627
|
+
|
|
628
|
+
---
|
|
629
|
+
|
|
630
|
+
## 📄 许可证
|
|
631
|
+
|
|
632
|
+
MIT License
|
|
633
|
+
|
|
634
|
+
---
|
|
635
|
+
|
|
636
|
+
## 📧 联系方式
|
|
637
|
+
|
|
638
|
+
技术支持:请联系项目维护者
|
|
639
|
+
|
|
640
|
+
---
|
|
641
|
+
|
|
642
|
+
**最后更新**: 2026-04-02
|
|
643
|
+
**版本**: 0.2.0
|
|
644
|
+
**作者**: 松涵
|