microframex 2026.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.
- microframex-2026.1/PKG-INFO +13 -0
- microframex-2026.1/microframe/__init__.py +2 -0
- microframex-2026.1/microframe/dataframe.py +75 -0
- microframex-2026.1/microframe/reader.py +66 -0
- microframex-2026.1/microframe/writer.py +4 -0
- microframex-2026.1/microframex.egg-info/PKG-INFO +13 -0
- microframex-2026.1/microframex.egg-info/SOURCES.txt +10 -0
- microframex-2026.1/microframex.egg-info/dependency_links.txt +1 -0
- microframex-2026.1/microframex.egg-info/requires.txt +3 -0
- microframex-2026.1/microframex.egg-info/top_level.txt +1 -0
- microframex-2026.1/setup.cfg +4 -0
- microframex-2026.1/setup.py +15 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: microframex
|
|
3
|
+
Version: 2026.1
|
|
4
|
+
Summary: 一个轻量级数据框架
|
|
5
|
+
Author: 唐旭东
|
|
6
|
+
Requires-Python: >=3.7
|
|
7
|
+
Requires-Dist: openpyxl
|
|
8
|
+
Requires-Dist: sqlalchemy
|
|
9
|
+
Requires-Dist: colorama
|
|
10
|
+
Dynamic: author
|
|
11
|
+
Dynamic: requires-dist
|
|
12
|
+
Dynamic: requires-python
|
|
13
|
+
Dynamic: summary
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
class DataFrame:
|
|
2
|
+
def __init__(self, rows, columns=None):
|
|
3
|
+
|
|
4
|
+
rows = list(rows) # 🔥 强制统一
|
|
5
|
+
self.rows = []
|
|
6
|
+
|
|
7
|
+
if not rows:
|
|
8
|
+
return
|
|
9
|
+
|
|
10
|
+
# ========= dict 输入 =========
|
|
11
|
+
if isinstance(rows[0], dict):
|
|
12
|
+
self.rows = rows
|
|
13
|
+
return
|
|
14
|
+
|
|
15
|
+
# ========= row + columns =========
|
|
16
|
+
if not columns:
|
|
17
|
+
columns = list(rows[0])
|
|
18
|
+
rows = rows[1:]
|
|
19
|
+
|
|
20
|
+
self.rows = [
|
|
21
|
+
dict(zip(columns, row))
|
|
22
|
+
for row in rows
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
def validate_keys(self, keys):
|
|
26
|
+
cols = set(self.columns)
|
|
27
|
+
keys = set(keys)
|
|
28
|
+
|
|
29
|
+
missing = keys - cols
|
|
30
|
+
if missing:
|
|
31
|
+
raise KeyError(f"字段 “{missing}” 不存在")
|
|
32
|
+
|
|
33
|
+
@property
|
|
34
|
+
def columns(self):
|
|
35
|
+
if not self.rows:
|
|
36
|
+
return []
|
|
37
|
+
return list(self.rows[0].keys())
|
|
38
|
+
|
|
39
|
+
def head(self, n=5):
|
|
40
|
+
return DataFrame(self.rows[:n])
|
|
41
|
+
|
|
42
|
+
def groupby(self, *keys):
|
|
43
|
+
|
|
44
|
+
# 👉 统一校验
|
|
45
|
+
self.validate_keys(keys)
|
|
46
|
+
|
|
47
|
+
groups = {}
|
|
48
|
+
|
|
49
|
+
for row in self.rows:
|
|
50
|
+
|
|
51
|
+
if len(keys) == 1:
|
|
52
|
+
k = row.get(keys[0])
|
|
53
|
+
else:
|
|
54
|
+
k = tuple(row.get(key) for key in keys)
|
|
55
|
+
|
|
56
|
+
groups.setdefault(k, []).append(row)
|
|
57
|
+
|
|
58
|
+
return {k: DataFrame(v) for k, v in groups.items()}
|
|
59
|
+
|
|
60
|
+
def __repr__(self):
|
|
61
|
+
n = min(5, len(self.rows))
|
|
62
|
+
preview = self.rows[:n]
|
|
63
|
+
|
|
64
|
+
col_count = len(self.columns)
|
|
65
|
+
|
|
66
|
+
lines = [f"DataFrame(rows={len(self.rows)}, cols={col_count})("]
|
|
67
|
+
|
|
68
|
+
for row in preview:
|
|
69
|
+
lines.append(f" {row}")
|
|
70
|
+
|
|
71
|
+
if len(self.rows) > 5:
|
|
72
|
+
lines.append(f" ...")
|
|
73
|
+
|
|
74
|
+
lines.append(")")
|
|
75
|
+
return "\n".join(lines)
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
from datetime import datetime
|
|
2
|
+
from os.path import basename
|
|
3
|
+
from .dataframe import DataFrame
|
|
4
|
+
from openpyxl import load_workbook
|
|
5
|
+
from sqlalchemy import create_engine, text
|
|
6
|
+
|
|
7
|
+
def format_datetime_with_milliseconds():
|
|
8
|
+
"""格式化时间为 2026-03-12 14:17:45.618 格式"""
|
|
9
|
+
dt = datetime.now()
|
|
10
|
+
# 获取日期时间部分(不含毫秒)
|
|
11
|
+
base_time = dt.strftime("%Y-%m-%d %H:%M:%S")
|
|
12
|
+
# 获取毫秒(微秒除以1000)
|
|
13
|
+
milliseconds = dt.microsecond // 1000
|
|
14
|
+
# 格式化毫秒为3位数,不足补零
|
|
15
|
+
ms_str = f"{milliseconds:03d}"
|
|
16
|
+
return f"{base_time}.{ms_str}"
|
|
17
|
+
|
|
18
|
+
def load(source, sheet_name=None, query=None):
|
|
19
|
+
"""
|
|
20
|
+
读取数据源并返回 DataFrame
|
|
21
|
+
|
|
22
|
+
Parameters
|
|
23
|
+
----------
|
|
24
|
+
source : str
|
|
25
|
+
- Excel 文件路径(.xlsx)
|
|
26
|
+
- MySQL 连接字符串(mysql+pymysql://user:pwd@host/db)
|
|
27
|
+
sheet_name : str, optional
|
|
28
|
+
Excel sheet 名称(默认第一个 sheet)
|
|
29
|
+
query : str, optional
|
|
30
|
+
SQL 查询语句(仅数据库模式必填)
|
|
31
|
+
|
|
32
|
+
Returns
|
|
33
|
+
-------
|
|
34
|
+
DataFrame
|
|
35
|
+
microframe.DataFrame
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
# ========== 1. Excel ==========
|
|
39
|
+
if source.lower().endswith(".xlsx"):
|
|
40
|
+
wb = load_workbook(source, read_only=True, data_only=True)
|
|
41
|
+
|
|
42
|
+
ws = wb[sheet_name] if sheet_name else wb.active
|
|
43
|
+
|
|
44
|
+
sheet_name = sheet_name if sheet_name else ws.title
|
|
45
|
+
|
|
46
|
+
print(f'\033[32m{format_datetime_with_milliseconds()} \033[31m| \033[0mINFO \033[31m|\033[0m 读取excel文件名称:\033[35m“{basename(source)}”\033[0m,sheet名称:\033[35m“{sheet_name}”\033[0m')
|
|
47
|
+
|
|
48
|
+
data = list(ws.values)
|
|
49
|
+
return DataFrame(data)
|
|
50
|
+
|
|
51
|
+
# ========== 2. MySQL ==========
|
|
52
|
+
if source.startswith("mysql"):
|
|
53
|
+
if not query:
|
|
54
|
+
raise ValueError("数据库模式下必须提供 query")
|
|
55
|
+
|
|
56
|
+
engine = create_engine(source)
|
|
57
|
+
|
|
58
|
+
with engine.connect() as conn:
|
|
59
|
+
result = conn.execute(text(query))
|
|
60
|
+
rows = result.fetchall()
|
|
61
|
+
columns = result.keys()
|
|
62
|
+
|
|
63
|
+
return DataFrame(rows, columns = columns)
|
|
64
|
+
|
|
65
|
+
# ========== 3. 不支持的数据源 ==========
|
|
66
|
+
raise ValueError(f"不支持的数据源类型: {source}")
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: microframex
|
|
3
|
+
Version: 2026.1
|
|
4
|
+
Summary: 一个轻量级数据框架
|
|
5
|
+
Author: 唐旭东
|
|
6
|
+
Requires-Python: >=3.7
|
|
7
|
+
Requires-Dist: openpyxl
|
|
8
|
+
Requires-Dist: sqlalchemy
|
|
9
|
+
Requires-Dist: colorama
|
|
10
|
+
Dynamic: author
|
|
11
|
+
Dynamic: requires-dist
|
|
12
|
+
Dynamic: requires-python
|
|
13
|
+
Dynamic: summary
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
setup.py
|
|
2
|
+
microframe/__init__.py
|
|
3
|
+
microframe/dataframe.py
|
|
4
|
+
microframe/reader.py
|
|
5
|
+
microframe/writer.py
|
|
6
|
+
microframex.egg-info/PKG-INFO
|
|
7
|
+
microframex.egg-info/SOURCES.txt
|
|
8
|
+
microframex.egg-info/dependency_links.txt
|
|
9
|
+
microframex.egg-info/requires.txt
|
|
10
|
+
microframex.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
microframe
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
from setuptools import setup, find_packages
|
|
2
|
+
|
|
3
|
+
setup(
|
|
4
|
+
name="microframex",
|
|
5
|
+
version="2026.1",
|
|
6
|
+
author="唐旭东",
|
|
7
|
+
description="一个轻量级数据框架",
|
|
8
|
+
packages=find_packages(),
|
|
9
|
+
install_requires=[
|
|
10
|
+
"openpyxl",
|
|
11
|
+
"sqlalchemy",
|
|
12
|
+
"colorama"
|
|
13
|
+
],
|
|
14
|
+
python_requires=">=3.7",
|
|
15
|
+
)
|