mdbq 0.4.6__tar.gz → 1.0.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.
Files changed (46) hide show
  1. {mdbq-0.4.6 → mdbq-1.0.0}/PKG-INFO +1 -1
  2. {mdbq-0.4.6 → mdbq-1.0.0}/mdbq/aggregation/aggregation.py +27 -140
  3. mdbq-1.0.0/mdbq/aggregation/df_types.py +180 -0
  4. mdbq-1.0.0/mdbq/aggregation/mysql_types.py +231 -0
  5. mdbq-0.4.6/mdbq/mysql/data_types.py → mdbq-1.0.0/mdbq/mysql/data_types_/345/215/263/345/260/206/345/210/240/351/231/244.py +19 -8
  6. {mdbq-0.4.6 → mdbq-1.0.0}/mdbq/mysql/mysql.py +55 -204
  7. {mdbq-0.4.6 → mdbq-1.0.0}/mdbq.egg-info/PKG-INFO +1 -1
  8. {mdbq-0.4.6 → mdbq-1.0.0}/mdbq.egg-info/SOURCES.txt +3 -1
  9. {mdbq-0.4.6 → mdbq-1.0.0}/setup.py +1 -1
  10. {mdbq-0.4.6 → mdbq-1.0.0}/README.txt +0 -0
  11. {mdbq-0.4.6 → mdbq-1.0.0}/mdbq/__init__.py +0 -0
  12. {mdbq-0.4.6 → mdbq-1.0.0}/mdbq/__version__.py +0 -0
  13. {mdbq-0.4.6 → mdbq-1.0.0}/mdbq/aggregation/__init__.py +0 -0
  14. {mdbq-0.4.6 → mdbq-1.0.0}/mdbq/aggregation/optimize_data.py +0 -0
  15. {mdbq-0.4.6 → mdbq-1.0.0}/mdbq/aggregation/query_data.py +0 -0
  16. {mdbq-0.4.6 → mdbq-1.0.0}/mdbq/bdup/__init__.py +0 -0
  17. {mdbq-0.4.6 → mdbq-1.0.0}/mdbq/bdup/bdup.py +0 -0
  18. {mdbq-0.4.6 → mdbq-1.0.0}/mdbq/clean/__init__.py +0 -0
  19. {mdbq-0.4.6 → mdbq-1.0.0}/mdbq/clean/data_clean.py +0 -0
  20. {mdbq-0.4.6 → mdbq-1.0.0}/mdbq/company/__init__.py +0 -0
  21. {mdbq-0.4.6 → mdbq-1.0.0}/mdbq/company/copysh.py +0 -0
  22. {mdbq-0.4.6 → mdbq-1.0.0}/mdbq/config/__init__.py +0 -0
  23. {mdbq-0.4.6 → mdbq-1.0.0}/mdbq/config/get_myconf.py +0 -0
  24. {mdbq-0.4.6 → mdbq-1.0.0}/mdbq/config/products.py +0 -0
  25. {mdbq-0.4.6 → mdbq-1.0.0}/mdbq/config/set_support.py +0 -0
  26. {mdbq-0.4.6 → mdbq-1.0.0}/mdbq/config/update_conf.py +0 -0
  27. {mdbq-0.4.6 → mdbq-1.0.0}/mdbq/dataframe/__init__.py +0 -0
  28. {mdbq-0.4.6 → mdbq-1.0.0}/mdbq/dataframe/converter.py +0 -0
  29. {mdbq-0.4.6 → mdbq-1.0.0}/mdbq/log/__init__.py +0 -0
  30. {mdbq-0.4.6 → mdbq-1.0.0}/mdbq/log/mylogger.py +0 -0
  31. {mdbq-0.4.6 → mdbq-1.0.0}/mdbq/mongo/__init__.py +0 -0
  32. {mdbq-0.4.6 → mdbq-1.0.0}/mdbq/mongo/mongo.py +0 -0
  33. {mdbq-0.4.6 → mdbq-1.0.0}/mdbq/mysql/__init__.py +0 -0
  34. {mdbq-0.4.6 → mdbq-1.0.0}/mdbq/mysql/s_query.py +0 -0
  35. {mdbq-0.4.6 → mdbq-1.0.0}/mdbq/mysql/year_month_day.py +0 -0
  36. {mdbq-0.4.6 → mdbq-1.0.0}/mdbq/other/__init__.py +0 -0
  37. {mdbq-0.4.6 → mdbq-1.0.0}/mdbq/other/porxy.py +0 -0
  38. {mdbq-0.4.6 → mdbq-1.0.0}/mdbq/other/pov_city.py +0 -0
  39. {mdbq-0.4.6 → mdbq-1.0.0}/mdbq/other/ua_sj.py +0 -0
  40. {mdbq-0.4.6 → mdbq-1.0.0}/mdbq/pbix/__init__.py +0 -0
  41. {mdbq-0.4.6 → mdbq-1.0.0}/mdbq/pbix/pbix_refresh.py +0 -0
  42. {mdbq-0.4.6 → mdbq-1.0.0}/mdbq/pbix/refresh_all.py +0 -0
  43. {mdbq-0.4.6 → mdbq-1.0.0}/mdbq/spider/__init__.py +0 -0
  44. {mdbq-0.4.6 → mdbq-1.0.0}/mdbq.egg-info/dependency_links.txt +0 -0
  45. {mdbq-0.4.6 → mdbq-1.0.0}/mdbq.egg-info/top_level.txt +0 -0
  46. {mdbq-0.4.6 → mdbq-1.0.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: mdbq
3
- Version: 0.4.6
3
+ Version: 1.0.0
4
4
  Home-page: https://pypi.org/project/mdbsql
5
5
  Author: xigua,
6
6
  Author-email: 2587125111@qq.com
@@ -11,6 +11,7 @@ import platform
11
11
  import json
12
12
  from mdbq.mongo import mongo
13
13
  from mdbq.mysql import mysql
14
+ from mdbq.aggregation import df_types
14
15
  from mdbq.config import get_myconf
15
16
  from mdbq.config import set_support
16
17
  from mdbq.dataframe import converter
@@ -25,109 +26,15 @@ warnings.filterwarnings('ignore')
25
26
  1. DatabaseUpdate: 程序用于对爬虫下载的原始数据进行清洗并入库;
26
27
  数据清洗主要包括对字段名的非法字符处理,对 df 中的非法值进行预处理;
27
28
  数据入库时会较检并更新本地 json 文件的 dtypes 信息;
28
- 若 json 缺失 dtypes 信息, 可用 update_dtypte 先更新, 或者手动修改添加本地 json 信息;
29
+ 若 json 缺失 dtypes 信息, 可用 update_df_types_to_json 先更新, 或者手动修改添加本地 json 信息;
29
30
  2. DataTypes: 类用于将某个csv文件的 dtypes 信息存入本地 json 文件, 会调用 converter 对 df 预处理;
30
31
  作用于完善某个数据库 dtypes 信息,可以使用本函数更新;
31
- 3. update_dtypte: 函数将一个 csv 文件的 dtypes 信息更新至本地 json 文件;
32
+ 3. update_df_types_to_json: 函数将一个 csv 文件的 dtypes 信息更新至本地 json 文件;
32
33
  4. upload: 函数将一个文件夹上传至数据库;
33
- 如果本地 json 中确实这个数据库的 dtypes 信息, 请用 update_dtypte 更新 json 文件再执行数据上传;
34
+ 如果本地 json 中确实这个数据库的 dtypes 信息, 请用 update_df_types_to_json 更新 json 文件再执行数据上传;
34
35
  """
35
36
 
36
37
 
37
- class DataTypes:
38
- """
39
- 将某表的列信息添加到 json 示例:
40
- file = '/Users/xigua/Downloads/天猫直通车旧报表(未排重版本).csv'
41
- df = pd.read_csv(file, encoding='utf-8_sig', header=0, na_filter=False)
42
- d = DataTypes()
43
- d.read_dtypes(
44
- df=df,
45
- db_name='天猫数据2',
46
- collection_name='旧版报表',
47
- is_file_dtype=False, # 关闭文件优先
48
- )
49
- d.dtypes_to_file()
50
- """
51
- def __init__(self):
52
- self.path = set_support.SetSupport(dirname='support').dirname
53
- if not os.path.exists(self.path):
54
- os.mkdir(self.path)
55
- self.json_file = os.path.join(self.path, 'data_types.json')
56
- # self.datas = json.loads('{}') # 等待写入 json 文件的 dtypes 数据
57
- self.datas = {'json统计': {'数据库量': 0, '集合数量': 0, '字段量': 0}}
58
- self.json_before()
59
-
60
- def json_before(self):
61
- """ 本地 json 文件的 dtypes 信息, 初始化更新给 self.datas """
62
- if os.path.isfile(self.json_file):
63
- with open(self.json_file, 'r', encoding='utf-8_sig') as json_file:
64
- json_ = json.load(json_file)
65
- self.datas.update(json_)
66
-
67
- def load_dtypes(self, db_name, collection_name, ):
68
- return self.datas[db_name][collection_name]
69
-
70
-
71
- def read_dtypes(self, db_name, collection_name, df=pd.DataFrame(), is_file_dtype=True):
72
- """
73
- 读取 df 的 dtypes, 并更新本地 json 文件
74
- 期间会 清理不合规的列名, 并对数据类型进行转换(尝试将 object 类型转为 int 或 float)
75
- 返回: df 的 dtypes, 后续使用示例: df = df.astype(dtypes, errors='ignore')
76
- is_file_dtype=True: 默认情况下以旧 json 优先, 即允许手动指定 json 文件里面的数据类型
77
- """
78
- if len(df) == 0:
79
- return
80
- cv = converter.DataFrameConverter()
81
- df = cv.convert_df_cols(df=df) # 清理 dataframe 列名的不合规字符
82
- dtypes = df.dtypes.apply(str).to_dict()
83
- dtypes = {db_name: {collection_name: dtypes}}
84
-
85
- if not self.datas: # 如果不存在本地 json 文件, 直接返回即可
86
- self.datas.update(dtypes)
87
- return self.datas[db_name][collection_name]
88
- else: # 存在则读取,并更新 df 的 dtypes
89
- if db_name in list(self.datas.keys()): # ['京东数据2', '天猫数据2', '生意参谋数据2', '生意经2']
90
- if collection_name in list(self.datas[db_name].keys()):
91
- if is_file_dtype: # 旧数据优先
92
- # # 用 dtypes 更新, 允许手动指定 json 文件里面的数据类型
93
- dtypes[db_name][collection_name].update(self.datas[db_name][collection_name])
94
- # 将 dtypes 更新进去,使 self.datas 包含新旧信息
95
- self.datas[db_name][collection_name].update(dtypes[db_name][collection_name])
96
- else: # 新数据优先
97
- self.datas[db_name][collection_name].update(dtypes[db_name][collection_name])
98
- else:
99
- if is_file_dtype: # 旧数据优先
100
- dtypes[db_name].update(self.datas[db_name])
101
- self.datas[db_name].update(dtypes[db_name])
102
- else:
103
- self.datas[db_name].update(dtypes[db_name])
104
- else:
105
- # dtypes.update(self.datas) # 可以注释掉, 因为旧数据 self.datas 是空的
106
- self.datas.update(dtypes)
107
- dbs = 0
108
- collections = 0
109
- cols = 0
110
- # self.datas.pop('json统计')
111
- for k, v in self.datas.items():
112
- if k == 'json统计':
113
- continue
114
- dbs += 1
115
- for d, j in v.items():
116
- collections += 1
117
- for t, p in j.items():
118
- cols += 1
119
- tips = {'json统计': {'数据库量': dbs, '集合数量': collections, '字段量': cols}}
120
- self.datas.update(tips)
121
- return self.datas[db_name][collection_name] # 返回 df 的 dtypes
122
-
123
- def dtypes_to_file(self):
124
- """ 保存为本地 json 文件 """
125
- # print(self.datas)
126
- with open(self.json_file, 'w', encoding='utf-8_sig') as f:
127
- json.dump(self.datas, f, ensure_ascii=False, sort_keys=True, indent=4)
128
- time.sleep(1)
129
-
130
-
131
38
  class DatabaseUpdate:
132
39
  def __init__(self, path):
133
40
  self.path = path # 数据所在目录, 即: 下载文件夹
@@ -142,7 +49,6 @@ class DatabaseUpdate:
142
49
  print(f'1.1.0 初始化时传入了不存在的目录: {self.path}')
143
50
  return
144
51
 
145
- json_data = DataTypes() # json 文件, 包含数据的 dtypes 信息
146
52
  for root, dirs, files in os.walk(self.path, topdown=False):
147
53
  for name in files:
148
54
  if '~$' in name or '.DS' in name or '.localized' in name or '.ini' in name or '$RECYCLE.BIN' in name or 'Icon' in name:
@@ -680,13 +586,6 @@ class DatabaseUpdate:
680
586
  except Exception as e:
681
587
  print(f'{name}, {e}')
682
588
  if len(df) > 0:
683
- # 创建包含 dtypes 信息的 json 文件
684
- json_data.read_dtypes(
685
- df=df,
686
- db_name=db_name,
687
- collection_name=collection_name,
688
- is_file_dtype=True, # 默认本地文件优先: True
689
- )
690
589
  # 将数据传入 self.datas 等待更新进数据库
691
590
  self.datas.append(
692
591
  {
@@ -695,10 +594,8 @@ class DatabaseUpdate:
695
594
  '数据主体': df,
696
595
  }
697
596
  )
698
- json_data.dtypes_to_file() # 写入 json 文件, 包含数据的 dtypes 信息
699
597
 
700
598
  # 品销宝一个表格里面包含多个 sheet, 最好是单独处理
701
- json_data = DataTypes() # json 文件, 包含数据的 dtypes 信息
702
599
  for root, dirs, files in os.walk(self.path, topdown=False):
703
600
  for name in files:
704
601
  if '~$' in name or '.DS' in name or '.localized' in name or '.jpg' in name or '.png' in name:
@@ -720,12 +617,6 @@ class DatabaseUpdate:
720
617
  df.insert(loc=1, column='报表类型', value=sheet4)
721
618
  db_name = '天猫数据2'
722
619
  collection_name = f'推广数据_品销宝_{sheet4}'
723
- json_data.read_dtypes(
724
- df=df,
725
- db_name=db_name,
726
- collection_name=collection_name,
727
- is_file_dtype=False,
728
- )
729
620
  self.datas.append(
730
621
  {
731
622
  '数据库名': db_name,
@@ -735,7 +626,6 @@ class DatabaseUpdate:
735
626
  )
736
627
  if is_move:
737
628
  os.remove(os.path.join(root, name))
738
- json_data.dtypes_to_file() # 写入 json 文件, 包含数据的 dtypes 信息
739
629
 
740
630
  df = self.date_table() # 创建一个日期表
741
631
  self.datas.append(
@@ -750,6 +640,7 @@ class DatabaseUpdate:
750
640
  """
751
641
  将清洗后的 df 上传数据库
752
642
  """
643
+ df_to_json = dtypes.DataTypes() # json 文件, 包含数据的 dtypes 信息
753
644
  for service_database in service_databases:
754
645
  for service_name, database in service_database.items():
755
646
  # print(service_name, database)
@@ -766,7 +657,13 @@ class DatabaseUpdate:
766
657
  drop_duplicates=False,
767
658
  )
768
659
  for data in self.datas:
769
- df, db_name, collection_name = data['数据主体'], data['数据库名'], data['集合名称']
660
+ db_name, collection_name, df = data['数据库名'], data['集合名称'], data['数据主体']
661
+ df_to_json.get_df_types(
662
+ df=df,
663
+ db_name=db_name,
664
+ collection_name=collection_name,
665
+ is_file_dtype=True, # 默认本地文件优先: True
666
+ )
770
667
  d.df_to_mongo(df=df, db_name=db_name, collection_name=collection_name)
771
668
 
772
669
  elif database == 'mysql':
@@ -782,7 +679,14 @@ class DatabaseUpdate:
782
679
  )
783
680
  for data in self.datas:
784
681
  df, db_name, collection_name = data['数据主体'], data['数据库名'], data['集合名称']
682
+ df_to_json.get_df_types(
683
+ df=df,
684
+ db_name=db_name,
685
+ collection_name=collection_name,
686
+ is_file_dtype=True, # 默认本地文件优先: True
687
+ )
785
688
  m.df_to_mysql(df=df, db_name=db_name, tabel_name=collection_name)
689
+ df_to_json.as_json_file() # 写入 json 文件, 包含数据的 dtypes 信息
786
690
 
787
691
  def new_unzip(self, path=None, is_move=None):
788
692
  """
@@ -929,26 +833,9 @@ class DatabaseUpdate:
929
833
  df.sort_values('日期', ascending=False, ignore_index=True, inplace=True)
930
834
  return df
931
835
 
932
- def update_dtypte():
933
- """ 更新一个文件的 dtype 信息到 json 文件 """
934
- file = '/Users/xigua/数据中心/原始文件2/月数据/流量来源/【生意参谋平台】无线店铺流量来源-2023-04-01_2023-04-30.csv'
935
- df = pd.read_csv(file, encoding='utf-8_sig', header=0, na_filter=False)
936
- d = DataTypes()
937
- d.read_dtypes(
938
- df=df,
939
- db_name='生意参谋数据2',
940
- collection_name='店铺来源_月数据',
941
- is_file_dtype=True, # 日常需开启文件优先, 正常不要让新文件修改 json 已有的类型
942
- )
943
- d.dtypes_to_file()
944
-
945
836
 
946
- def upload():
837
+ def upload(path, db_name, collection_name):
947
838
  """ 上传一个文件夹到数据库 """
948
- path = '/Users/xigua/数据中心/原始文件2/生意经/店铺指标'
949
- db_name = '生意经2'
950
- collection_name = '店铺指标'
951
-
952
839
  username, password, host, port = get_myconf.select_config_values(
953
840
  target_service='home_lx',
954
841
  database='mongodb',
@@ -981,8 +868,8 @@ def upload():
981
868
  port=port,
982
869
  )
983
870
 
984
- dt = DataTypes()
985
- dtypes = dt.load_dtypes(
871
+ df_to_json = df_types.DataTypes()
872
+ dtypes = df_to_json.load_dtypes(
986
873
  db_name=db_name,
987
874
  collection_name=collection_name,
988
875
  )
@@ -1007,8 +894,6 @@ def upload():
1007
894
  intersection_keys = dtypes.keys() & old_dt.keys() # 获取两个字典键的交集
1008
895
  dtypes = {k: dtypes[k] for k in intersection_keys} # 使用交集的键创建新字典
1009
896
  df = df.astype(dtypes)
1010
- # print(intersection_dict)
1011
- # print(df)
1012
897
 
1013
898
  d.df_to_mongo(df=df, db_name=db_name, collection_name=collection_name)
1014
899
  m.df_to_mysql(df=df, db_name=db_name, tabel_name=collection_name)
@@ -1034,6 +919,8 @@ def main():
1034
919
  if __name__ == '__main__':
1035
920
  # username, password, host, port = get_myconf.select_config_values(target_service='nas', database='mysql')
1036
921
  # print(username, password, host, port)
1037
-
1038
- # main()
1039
- upload()
922
+ upload(
923
+ path='/Users/xigua/数据中心/原始文件2/生意经/地域分布',
924
+ db_name = '生意经2',
925
+ collection_name = '省份城市分析',
926
+ )
@@ -0,0 +1,180 @@
1
+ # -*- coding:utf-8 -*-
2
+ import warnings
3
+ import pandas as pd
4
+ import numpy as np
5
+ import chardet
6
+ import zipfile
7
+
8
+ from numpy import dtype
9
+ from pandas.tseries.holiday import next_monday
10
+ from pyzipper import PyZipFile
11
+ import os
12
+ import platform
13
+ import json
14
+ import pymysql
15
+ from mdbq.mongo import mongo
16
+ from mdbq.mysql import mysql
17
+ from mdbq.mysql import s_query
18
+ from mdbq.config import get_myconf
19
+ from mdbq.config import set_support
20
+ from mdbq.dataframe import converter
21
+ import datetime
22
+ import time
23
+ import re
24
+ import shutil
25
+ import getpass
26
+
27
+ from sqlalchemy.dialects.postgresql.pg_catalog import pg_get_serial_sequence
28
+
29
+ warnings.filterwarnings('ignore')
30
+ """
31
+ 1. 记录 dataframe 或者数据库的列信息(dtypes)
32
+ 2. 更新 mysql 中所有数据库的 dtypes 信息到本地 json
33
+ """
34
+
35
+
36
+ class DataTypes:
37
+ """
38
+ 数据简介: 记录 dataframe 或者数据库的列信息(dtypes),可以记录其信息或者加载相关信息用于入库使用,
39
+ 第一字段为分类(如 dataframe/mysql),第二字段为数据库名,第三字段为集合名,第四段列名及其数据类型
40
+ """
41
+ def __init__(self):
42
+ self.datas = {
43
+ "json统计":
44
+ {
45
+ "字段量": 0,
46
+ "数据库量": 0,
47
+ "集合数量": 0
48
+ }
49
+ }
50
+ self.path = set_support.SetSupport(dirname='support').dirname
51
+ self.json_file = os.path.join(self.path, 'df_types.json')
52
+ if not os.path.isdir(self.path):
53
+ os.makedirs(self.path)
54
+ if not os.path.isfile(self.json_file):
55
+ with open(self.json_file, 'w', encoding='utf-8_sig') as f:
56
+ json.dump(self.datas, f, ensure_ascii=False, sort_keys=True, indent=4)
57
+ self.json_before()
58
+
59
+ def json_before(self):
60
+ """ 本地 json 文件的 dtypes 信息, 初始化更新给 self.datas """
61
+ with open(self.json_file, 'r', encoding='utf-8_sig') as f:
62
+ json_ = json.load(f)
63
+ self.datas.update(json_)
64
+
65
+ def get_df_types(self, db_name, collection_name, df=pd.DataFrame(), is_file_dtype=True):
66
+ """
67
+ 读取 df 的 dtypes, 并更新本地 json 文件
68
+ 期间会 清理不合规的列名, 并对数据类型进行转换(尝试将 object 类型转为 int 或 float)
69
+ 返回: df 的 dtypes, 后续使用示例: df = df.astype(dtypes, errors='ignore')
70
+ is_file_dtype=True: 默认情况下以旧 json 优先, 即允许手动指定 json 文件里面的数据类型
71
+ """
72
+ if len(df) == 0:
73
+ return
74
+ cv = converter.DataFrameConverter()
75
+ df = cv.convert_df_cols(df=df) # 清理 dataframe 非法值
76
+ dtypes = df.dtypes.apply(str).to_dict()
77
+ dtypes = {db_name: {collection_name: dtypes}}
78
+
79
+ if not self.datas: # 如果不存在本地 json 文件, 直接返回即可
80
+ self.datas.update(dtypes)
81
+ return self.datas[db_name][collection_name]
82
+ else: # 存在则读取,并更新 df 的 dtypes
83
+ if db_name in list(self.datas.keys()): # ['京东数据2', '天猫数据2', '生意参谋数据2', '生意经2']
84
+ if collection_name in list(self.datas[db_name].keys()):
85
+ if is_file_dtype: # 旧数据优先
86
+ # # 用 dtypes 更新, 允许手动指定 json 文件里面的数据类型
87
+ dtypes[db_name][collection_name].update(self.datas[db_name][collection_name])
88
+ # 将 dtypes 更新进去,使 self.datas 包含新旧信息
89
+ self.datas[db_name][collection_name].update(dtypes[db_name][collection_name])
90
+ else: # 新数据优先
91
+ self.datas[db_name][collection_name].update(dtypes[db_name][collection_name])
92
+ else:
93
+ if is_file_dtype: # 旧数据优先
94
+ dtypes[db_name].update(self.datas[db_name])
95
+ self.datas[db_name].update(dtypes[db_name])
96
+ else:
97
+ self.datas[db_name].update(dtypes[db_name])
98
+ else:
99
+ # dtypes.update(self.datas) # 可以注释掉, 因为旧数据 self.datas 是空的
100
+ self.datas.update(dtypes)
101
+ dbs = 0
102
+ collections = 0
103
+ cols = 0
104
+ # self.datas.pop('json统计')
105
+ for k, v in self.datas.items():
106
+ if k == 'json统计':
107
+ continue
108
+ dbs += 1
109
+ for d, j in v.items():
110
+ collections += 1
111
+ for t, p in j.items():
112
+ cols += 1
113
+ tips = {'json统计': {'数据库量': dbs, '集合数量': collections, '字段量': cols}}
114
+ self.datas.update(tips)
115
+ return self.datas[db_name][collection_name] # 返回 df 的 dtypes
116
+
117
+ def as_json_file(self):
118
+ """ 保存为本地 json 文件 """
119
+ with open(self.json_file, 'w', encoding='utf-8_sig') as f:
120
+ json.dump(
121
+ self.datas,
122
+ f,
123
+ ensure_ascii=False, # 默认True,非ASCII字符将被转义。如为False,则非ASCII字符会以\uXXXX输出
124
+ sort_keys=True, # 默认为False。如果为True,则字典的输出将按键排序。
125
+ indent=4,
126
+ )
127
+ time.sleep(1)
128
+
129
+ def df_dtypes_to_json(self, db_name, collection_name, path, df=pd.DataFrame(), is_file_dtype=True):
130
+ if len(df) == 0:
131
+ return
132
+ cv = converter.DataFrameConverter()
133
+ df = cv.convert_df_cols(df=df) # 清理 dataframe 列名的不合规字符
134
+ dtypes = df.dtypes.apply(str).to_dict()
135
+ dtypes = {'dataframe': {db_name: {collection_name: dtypes}}}
136
+ self.dtypes_to_json(dtypes=dtypes, cl='dataframe', db_name=db_name, collection_name=collection_name, path=path, is_file_dtype=is_file_dtype)
137
+
138
+ def load_dtypes(self, db_name, collection_name):
139
+ if db_name in list(self.datas.keys()):
140
+ if collection_name in list(self.datas[db_name].keys()):
141
+ return self.datas[db_name][collection_name]
142
+ else:
143
+ print(f'不存在的集合名信息: {collection_name}, 文件位置: {self.json_file}')
144
+ return {}
145
+ else:
146
+ print(f'不存在的数据库信息: {db_name}, 文件位置: {self.json_file}')
147
+ return {}
148
+
149
+
150
+ def update_df_types_to_json(file, db_name, collection_name, is_file_dtype=True):
151
+ """ 更新一个文件的 dtype 信息到 json 文件 """
152
+ df = pd.read_csv(file, encoding='utf-8_sig', header=0, na_filter=False)
153
+ df_to_json = DataTypes()
154
+ df_to_json.get_df_types(
155
+ df=df,
156
+ db_name=db_name,
157
+ collection_name=collection_name,
158
+ is_file_dtype=is_file_dtype, # 日常需开启文件优先, 正常不要让新文件修改 json 已有的类型
159
+ )
160
+ df_to_json.as_json_file()
161
+ print(f'json文件已存储: {df_to_json.json_file}')
162
+
163
+
164
+ def test_load_dtypes(db_name, collection_name):
165
+ d = DataTypes()
166
+ res = d.load_dtypes(db_name=db_name, collection_name=collection_name)
167
+ print(res)
168
+
169
+
170
+ if __name__ == '__main__':
171
+ file = '/Users/xigua/数据中心/pandas数据源/店铺日报.csv'
172
+ update_df_types_to_json(
173
+ file=file,
174
+ db_name='pandas数据源',
175
+ collection_name='店铺日报',
176
+ is_file_dtype=True,
177
+ )
178
+ # test_load_dtypes(db_name='pandas数据源', collection_name='店铺日报')
179
+
180
+
@@ -0,0 +1,231 @@
1
+ # -*- coding:utf-8 -*-
2
+ import warnings
3
+ import pandas as pd
4
+ import numpy as np
5
+ import chardet
6
+ import zipfile
7
+
8
+ from numpy import dtype
9
+ from pandas.tseries.holiday import next_monday
10
+ from pyzipper import PyZipFile
11
+ import os
12
+ import platform
13
+ import json
14
+ import pymysql
15
+ from mdbq.mongo import mongo
16
+ from mdbq.mysql import mysql
17
+ from mdbq.mysql import s_query
18
+ from mdbq.config import get_myconf
19
+ from mdbq.config import set_support
20
+ from mdbq.dataframe import converter
21
+ import datetime
22
+ import time
23
+ import re
24
+ import shutil
25
+ import getpass
26
+
27
+ from sqlalchemy.dialects.postgresql.pg_catalog import pg_get_serial_sequence
28
+
29
+ warnings.filterwarnings('ignore')
30
+ """
31
+ 1. 记录 dataframe 或者数据库的列信息(dtypes)
32
+ 2. 更新 mysql 中所有数据库的 dtypes 信息到本地 json
33
+ """
34
+
35
+
36
+ class DataTypes:
37
+ """
38
+ 数据简介: 记录 dataframe 或者数据库的列信息(dtypes),可以记录其信息或者加载相关信息用于入库使用,
39
+ 第一字段为分类(如 dataframe/mysql),第二字段为数据库名,第三字段为集合名,第四段列名及其数据类型
40
+ """
41
+ def __init__(self):
42
+ self.datas = {
43
+ '_json统计':
44
+ {
45
+ '分类': 0,
46
+ '数据库量': 0,
47
+ '集合数量': 0,
48
+ '字段量': 0,
49
+ '数据简介': '记录 dataframe 或者数据库的列信息(dtypes)',
50
+ }
51
+ }
52
+ self.path = set_support.SetSupport(dirname='support').dirname
53
+ self.json_file = os.path.join(self.path, 'mysql_types.json')
54
+ if not os.path.isdir(self.path):
55
+ os.makedirs(self.path)
56
+ if not os.path.isfile(self.json_file):
57
+ with open(self.json_file, 'w', encoding='utf-8_sig') as f:
58
+ json.dump(self.datas, f, ensure_ascii=False, sort_keys=True, indent=4)
59
+ self.json_before()
60
+
61
+ def json_before(self):
62
+ """ 本地 json 文件的 dtypes 信息, 初始化更新给 self.datas """
63
+ with open(self.json_file, 'r', encoding='utf-8_sig') as f:
64
+ json_ = json.load(f)
65
+ self.datas.update(json_)
66
+
67
+ def get_mysql_types(self, cl, dtypes, db_name, tabel_name, is_file_dtype=True):
68
+ """ 更新 mysql 的 types 信息到 json 文件 """
69
+ if cl in self.datas.keys():
70
+ if db_name in list(self.datas[cl].keys()): # ['京东数据2', '天猫数据2', '生意参谋数据2', '生意经2']
71
+ if tabel_name in list(self.datas[cl][db_name].keys()):
72
+ if is_file_dtype: # 旧数据优先
73
+ # # 用 dtypes 更新, 允许手动指定 json 文件里面的数据类型
74
+ dtypes[cl][db_name][tabel_name].update(self.datas[cl][db_name][tabel_name])
75
+ # 将 dtypes 更新进去,使 self.datas 包含新旧信息
76
+ self.datas[cl][db_name][tabel_name].update(dtypes[cl][db_name][tabel_name])
77
+ else: # 新数据优先
78
+ self.datas[cl][db_name][tabel_name].update(dtypes[cl][db_name][tabel_name])
79
+ else:
80
+ if is_file_dtype: # 旧数据优先
81
+ dtypes[cl][db_name].update(self.datas[cl][db_name])
82
+ self.datas[cl][db_name].update(dtypes[cl][db_name])
83
+ else:
84
+ self.datas[cl][db_name].update(dtypes[cl][db_name])
85
+ else:
86
+ # dtypes.update(self.datas) # 可以注释掉, 因为旧数据 self.datas 是空的
87
+ self.datas[cl].update(dtypes[cl])
88
+ else:
89
+ self.datas.update(dtypes)
90
+
91
+ cif = 0 # 分类
92
+ dbs = 0 # 数据库
93
+ collections = 0 # 集合
94
+ cols = 0 # 字段
95
+ for k, v in self.datas.items():
96
+ if k == '_json统计':
97
+ continue # 不统计头信息
98
+ cif += 1
99
+ for t, g in v.items():
100
+ dbs += 1
101
+ for d, j in g.items():
102
+ collections += 1
103
+ for t, p in j.items():
104
+ cols += 1
105
+ tips = {'分类': cif, '数据库量': dbs, '集合数量': collections, '字段量': cols}
106
+ self.datas['_json统计'].update(tips)
107
+ # with open(json_file, 'w', encoding='utf-8_sig') as f:
108
+ # json.dump(
109
+ # self.datas,
110
+ # f,
111
+ # ensure_ascii=False, # 默认True,非ASCII字符将被转义。如为False,则非ASCII字符会以\uXXXX输出
112
+ # sort_keys=True, # 默认为False。如果为True,则字典的输出将按键排序。
113
+ # indent=4,
114
+ # )
115
+
116
+ def as_json_file(self):
117
+ """ 保存为本地 json 文件 """
118
+ with open(self.json_file, 'w', encoding='utf-8_sig') as f:
119
+ json.dump(
120
+ self.datas,
121
+ f,
122
+ ensure_ascii=False, # 默认True,非ASCII字符将被转义。如为False,则非ASCII字符会以\uXXXX输出
123
+ sort_keys=True, # 默认为False。如果为True,则字典的输出将按键排序。
124
+ indent=4,
125
+ )
126
+ time.sleep(1)
127
+
128
+ def load_dtypes(self, db_name, tabel_name, cl='mysql', ):
129
+ """
130
+ mysql.py 程序从本地文件中读取 dtype 信息
131
+ 如果缺失 dtypes 信息,则执行 mysql_all_dtypes 以便更新所有数据库 dtypes 信息到 json 文件
132
+ """
133
+ if cl in self.datas.keys():
134
+ if db_name in list(self.datas[cl].keys()):
135
+ if tabel_name in list(self.datas[cl][db_name].keys()):
136
+ return self.datas[cl][db_name][tabel_name]
137
+ else:
138
+ print(f'不存在的集合名信息: {tabel_name}, 文件位置: {self.json_file}')
139
+ mysql_all_dtypes() # 更新 mysql 中所有数据库的 dtypes 信息到本地 json
140
+ return {}
141
+ else:
142
+ print(f'不存在的数据库信息: {db_name}, 文件位置: {self.json_file}')
143
+ mysql_all_dtypes() # 更新 mysql 中所有数据库的 dtypes 信息到本地 json
144
+ return {}
145
+ else:
146
+ print(f'不存在的数据分类: {cl}, 文件位置: {self.json_file}')
147
+ mysql_all_dtypes() # 更新 mysql 中所有数据库的 dtypes 信息到本地 json
148
+ return {}
149
+
150
+
151
+ def mysql_all_dtypes(path=None):
152
+ """
153
+ 更新笔记本 mysql 中所有数据库的 dtypes 信息到本地 json
154
+ """
155
+ if not path:
156
+ path = set_support.SetSupport(dirname='support').dirname
157
+
158
+ username, password, host, port = get_myconf.select_config_values(target_service='home_lx', database='mysql')
159
+ config = {
160
+ 'host': host,
161
+ 'port': port,
162
+ 'user': username,
163
+ 'password': password,
164
+ 'charset': 'utf8mb4', # utf8mb4 支持存储四字节的UTF-8字符集
165
+ 'cursorclass': pymysql.cursors.DictCursor,
166
+ }
167
+
168
+ connection = pymysql.connect(**config) # 连接数据库
169
+ with connection.cursor() as cursor:
170
+ sql = "SHOW DATABASES;"
171
+ cursor.execute(sql)
172
+ db_name_lists = cursor.fetchall()
173
+ db_name_lists = [item['Database'] for item in db_name_lists]
174
+ connection.close()
175
+
176
+ sys_lists = ['information_schema', 'mysql', 'performance_schema', 'sakila', 'sys']
177
+ db_name_lists = [item for item in db_name_lists if item not in sys_lists]
178
+
179
+ # db_name_lists = [
180
+ # '京东数据2',
181
+ # '天猫数据2',
182
+ # '市场数据2',
183
+ # '生意参谋数据2',
184
+ # '生意经2',
185
+ # '属性设置2',
186
+ # '聚合数据',
187
+ # ]
188
+ results = []
189
+ for db_name in db_name_lists:
190
+ config.update({'database': db_name}) # 添加更新 config 字段
191
+ connection = pymysql.connect(**config) # 连接数据库
192
+ try:
193
+ with connection.cursor() as cursor:
194
+ sql = f"SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA = '{db_name}';"
195
+ sql = "SHOW TABLES;"
196
+ cursor.execute(sql)
197
+ table_name = cursor.fetchall()
198
+ for table in table_name:
199
+ for k, v in table.items():
200
+ results.append({db_name: v})
201
+ except:
202
+ pass
203
+ finally:
204
+ connection.close()
205
+ time.sleep(0.5)
206
+
207
+ d = DataTypes()
208
+ for result in results:
209
+ for db_name, tabel_name in result.items():
210
+ print(f'获取列信息 数据库: < {db_name} >, 数据表: < {tabel_name} >')
211
+ # d.mysql_dtypes_to_json(db_name=db_name, tabel_name=tabel_name, path=path)
212
+ sq = s_query.QueryDatas(username=username, password=password, host=host, port=port)
213
+ # 获取数据表的指定列, 返回列表
214
+ # [{'视频bv号': 'BV1Dm4y1S7BU', '下载进度': 1}, {'视频bv号': 'BV1ov411c7US', '下载进度': 1}]
215
+ name_type = sq.dtypes_to_list(db_name=db_name, tabel_name=tabel_name)
216
+ if name_type:
217
+ dtypes = {item['COLUMN_NAME']: item['COLUMN_TYPE'] for item in name_type}
218
+ dtypes = {'mysql': {db_name: {tabel_name: dtypes}}}
219
+ d.get_mysql_types(
220
+ dtypes=dtypes,
221
+ cl='mysql',
222
+ db_name=db_name,
223
+ tabel_name=tabel_name,
224
+ is_file_dtype=True
225
+ )
226
+ else:
227
+ print(f'数据库回传数据(name_type)为空')
228
+ d.as_json_file()
229
+
230
+ if __name__ == '__main__':
231
+ mysql_all_dtypes() # 更新 mysql 中所有数据库的 dtypes 信息到本地 json
@@ -49,13 +49,19 @@ class DataTypes:
49
49
  '数据简介': '记录 dataframe 或者数据库的列信息(dtypes)',
50
50
  }
51
51
  }
52
+ self.path = set_support.SetSupport(dirname='support').dirname
53
+ self.json_file = os.path.join(self.path, 'mysql_types.json')
54
+ if not os.path.isdir(self.path):
55
+ os.makedirs(self.path)
56
+ if not os.path.isfile(self.json_file):
57
+ with open(self.json_file, 'w', encoding='utf-8_sig') as f:
58
+ json.dump(self.datas, f, ensure_ascii=False, sort_keys=True, indent=4)
52
59
 
53
- def json_before(self, json_file):
60
+ def json_before(self):
54
61
  """ 本地 json 文件的 dtypes 信息, 初始化更新给 self.datas """
55
- if os.path.isfile(json_file):
56
- with open(json_file, 'r', encoding='utf-8_sig') as f:
57
- json_ = json.load(f)
58
- self.datas.update(json_)
62
+ with open(self.json_file, 'r', encoding='utf-8_sig') as f:
63
+ json_ = json.load(f)
64
+ self.datas.update(json_)
59
65
 
60
66
  def df_dtypes_to_json(self, db_name, collection_name, path, df=pd.DataFrame(), is_file_dtype=True):
61
67
  if len(df) == 0:
@@ -148,7 +154,10 @@ class DataTypes:
148
154
  if os.path.isfile(json_file):
149
155
  self.json_before(json_file=json_file)
150
156
  else:
151
- print(f'不存在的文件: {json_file}')
157
+ # 如果不存在,则新建文件
158
+ with open(json_file, 'w', encoding='utf-8_sig') as f:
159
+ json.dump(self.datas, f, ensure_ascii=False, sort_keys=True, indent=4)
160
+ # print(f'不存在的文件: {json_file}')
152
161
  return
153
162
 
154
163
  if cl in self.datas.keys():
@@ -170,7 +179,7 @@ def mysql_all_dtypes(path=None):
170
179
  """
171
180
  更新笔记本 mysql 中所有数据库的 dtypes 信息到本地 json
172
181
  """
173
- if not os.path.isdir(path):
182
+ if not path:
174
183
  path = set_support.SetSupport(dirname='support').dirname
175
184
 
176
185
  username, password, host, port = get_myconf.select_config_values(target_service='home_lx', database='mysql')
@@ -229,4 +238,6 @@ def mysql_all_dtypes(path=None):
229
238
 
230
239
 
231
240
  if __name__ == '__main__':
232
- mysql_all_dtypes() # 更新 mysql 中所有数据库的 dtypes 信息到本地 json
241
+ # mysql_all_dtypes() # 更新 mysql 中所有数据库的 dtypes 信息到本地 json
242
+ d = DataTypes()
243
+
@@ -16,7 +16,7 @@ import calendar
16
16
  from mdbq.config import get_myconf
17
17
  from mdbq.config import set_support
18
18
  from mdbq.dataframe import converter
19
- from mdbq.mysql import data_types
19
+ from mdbq.aggregation import mysql_types
20
20
 
21
21
  warnings.filterwarnings('ignore')
22
22
 
@@ -35,153 +35,6 @@ class MysqlUpload:
35
35
  'charset': charset, # utf8mb4 支持存储四字节的UTF-8字符集
36
36
  'cursorclass': pymysql.cursors.DictCursor,
37
37
  }
38
- self.conn = None
39
-
40
- @staticmethod
41
- def try_except(func): # 在类内部定义一个异常处理方法
42
- @wraps(func)
43
- def wrapper(*args, **kwargs):
44
- try:
45
- return func(*args, **kwargs)
46
- except Exception as e:
47
- print(f'{func.__name__}, {e}') # 将异常信息返回
48
-
49
- return wrapper
50
-
51
- def _conn(self):
52
- self.config = {
53
- 'host': self.host,
54
- 'port': int(self.port),
55
- 'user': self.username,
56
- 'password': self.password,
57
- 'charset': 'utf8mb4', # utf8mb4 支持存储四字节的UTF-8字符集
58
- 'cursorclass': pymysql.cursors.DictCursor,
59
- }
60
- try:
61
- self.conn = pymysql.connect(**self.config) # 连接数据库
62
- return True
63
- except:
64
- return False
65
-
66
- # @try_except
67
- def df_to_mysql_bak(self, df, tabel_name, db_name='远程数据源'):
68
- """
69
- 将 df 写入数据库
70
- db_name: 数据库名称
71
- tabel_name: 集合/表名称
72
- """
73
- db_name = re.sub(r'[\',,()()/=<>+\-*^"’\[\]~#|&% .]', '_', db_name)
74
- tabel_name = re.sub(r'[\',,()()/=<>+\-*^"’\[\]~#|&% .]', '_', tabel_name)
75
- cv = converter.DataFrameConverter()
76
- df = cv.convert_df_cols(df=df) # 清理列名中的不合规字符
77
-
78
- connection = pymysql.connect(**self.config) # 连接数据库
79
- try:
80
- with connection.cursor() as cursor:
81
- cursor.execute(f"SHOW DATABASES LIKE '{db_name}'") # 检查数据库是否存在
82
- database_exists = cursor.fetchone()
83
- if not database_exists:
84
- # 如果数据库不存在,则新建
85
- if '8.138.27' in str(self.host) or platform.system() == "Linux": # 阿里云 mysql 低版本不支持 0900
86
- cursor.execute(f"CREATE DATABASE {db_name} COLLATE utf8mb4_unicode_ci")
87
- self.config.update({'charset': 'utf8mb4_unicode_ci'})
88
- if '192.168.1.100' in str(self.host):
89
- cursor.execute(f"CREATE DATABASE {db_name}")
90
- else:
91
- cursor.execute(f"CREATE DATABASE {db_name} COLLATE utf8mb4_0900_ai_ci")
92
- # cursor.execute(f"CREATE DATABASE {db_name}")
93
- connection.commit()
94
- print(f"创建Database: {db_name}")
95
- except Exception as e:
96
- print(e)
97
- return
98
- finally:
99
- connection.close() # 这里要断开连接
100
- time.sleep(0.2)
101
-
102
- self.config.update({'database': db_name}) # 添加更新 config 字段
103
- connection = pymysql.connect(**self.config) # 重新连接数据库
104
- try:
105
- with connection.cursor() as cursor:
106
- tabel_name = tabel_name.replace('-', '_')
107
- # 1. 查询表, 不存在则创建一个空表
108
- cursor.execute(f"SHOW TABLES LIKE '{tabel_name}'")
109
- if not cursor.fetchone():
110
- sql = f'CREATE TABLE IF NOT EXISTS {tabel_name} (id INT AUTO_INCREMENT PRIMARY KEY)'
111
- cursor.execute(sql)
112
- print(f'创建 mysql 表: {tabel_name}')
113
-
114
- # # 2. 列数据类型转换
115
- # cols = df.columns.tolist()
116
- # dtypes = df.dtypes.apply(str).to_dict() # 将 dataframe 数据类型转为字典形式
117
- # # 转换为 mysql 的数据类型
118
- # dtypes.update({col: self.convert_dtype_to_sql(df=df, col=col, dtype=dtypes[col]) for col in cols})
119
- dtypes = self.convert_dtypes(df=df, db_name=db_name, tabel_name=tabel_name)
120
-
121
- # 3. 检查列, 不存在则添加新列
122
- cols = df.columns.tolist()
123
- for col in cols:
124
- sql = ('SELECT 1 FROM information_schema.columns WHERE table_schema = %s AND table_name = %s AND '
125
- 'column_name = %s')
126
- cursor.execute(sql, (db_name, {tabel_name}, col))
127
- if cursor.fetchone() is None: # 如果列不存在,添加新列
128
- print(f"添加列: {col}({dtypes[col]})") # 添加列并指定数据类型
129
- # if col == '日期':
130
- # sql = f"ALTER TABLE {tabel_name} ADD COLUMN {col} DATE default NULL;"
131
- # else:
132
- # sql = f"ALTER TABLE {tabel_name} ADD COLUMN {col} mediumtext default NULL;"
133
- sql = f"ALTER TABLE {tabel_name} ADD COLUMN {col} {dtypes[col]} default NULL;"
134
- cursor.execute(sql)
135
-
136
- if col == '日期':
137
- cursor.execute(f"SHOW INDEXES FROM `{tabel_name}` WHERE Column_name = %s", ({col},))
138
- result = cursor.fetchone() # 检查索引是否存在
139
- if not result:
140
- # print(f'创建索引: {col}')
141
- cursor.execute(f"CREATE INDEX index_name ON {tabel_name}({col})")
142
- connection.commit() # 提交事务
143
-
144
- # # 4. 移除指定日期范围内的数据, 避免重复插入
145
- # dates = df['日期'].values.tolist()
146
- # start_date = pd.to_datetime(min(dates)).strftime('%Y-%m-%d')
147
- # end_date = (pd.to_datetime(max(dates)) + datetime.timedelta(days=1)).strftime('%Y-%m-%d')
148
- # sql = f"DELETE FROM {tabel_name} WHERE {'日期'} BETWEEN '%s' AND '%s'" % (start_date, end_date)
149
- # cursor.execute(sql)
150
- # connection.commit()
151
-
152
- # 5. 更新插入数据
153
- now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S ")
154
- print(f'{now}正在更新 mysql ({self.host}:{self.port}) {db_name}/{tabel_name}')
155
- if str(self.host) == '192.168.1.100': # 群晖服务器
156
- try:
157
- datas = df.to_dict('records')
158
- for data in datas:
159
- cols = ', '.join(data.keys())
160
- values = ', '.join([f'"{v}"' for v in data.values()])
161
- sql = f"INSERT INTO {tabel_name} ({cols}) VALUES ({values})"
162
- cursor.execute(sql)
163
- connection.commit()
164
- except Exception as e:
165
- print(e)
166
- connection.rollback()
167
- else: # 其他服务器
168
- try:
169
- engine = create_engine(
170
- f'mysql+pymysql://{self.username}:{self.password}@{self.host}:{self.port}/{db_name}'
171
- )
172
- df.to_sql(tabel_name, con=engine, if_exists='append', index=False)
173
- except Exception as e: # 如果异常则回滚
174
- try:
175
- connection.rollback()
176
- print(f'{e}, 发生异常,正在重试...')
177
- # df = df.replace([np.inf, -np.inf], 0)
178
- df.to_sql(tabel_name, con=engine, if_exists='append', index=False)
179
- except Exception as e:
180
- now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S ")
181
- print(f'{now}{db_name}/{tabel_name}数据异常, 正在回滚: {e}')
182
- connection.rollback()
183
- finally:
184
- connection.close()
185
38
 
186
39
  def df_to_mysql(self, df, tabel_name, db_name='远程数据源', drop_duplicates=False):
187
40
  """
@@ -221,7 +74,7 @@ class MysqlUpload:
221
74
  cursor.execute(sql)
222
75
  print(f'创建 mysql 表: {tabel_name}')
223
76
 
224
- # 2. 列数据类型转换
77
+ # 2. 列数据类型转换,将 df 数据类型转换为 mysql 的数据类型
225
78
  dtypes = self.convert_dtypes(df=df, db_name=db_name, tabel_name=tabel_name)
226
79
 
227
80
  # 有特殊字符不需转义
@@ -292,12 +145,10 @@ class MysqlUpload:
292
145
  2. json 文件中没有或者缺失部分列信息(利用 convert_dtype_to_sql 函数按指定规则转换缺失列)
293
146
  """
294
147
  cols = df.columns.tolist()
295
- path = set_support.SetSupport(dirname='support').dirname
296
- # json_file = os.path.join(path, 'mysql_types.json')
297
- # if os.path.isfile(json_file):
298
- d = data_types.DataTypes()
148
+ # path = set_support.SetSupport(dirname='support').dirname
149
+ d = mysql_types.DataTypes()
299
150
  # 从本地文件中读取 dtype 信息
300
- dtypes = d.load_dtypes(cl='mysql', db_name=db_name, collection_name=tabel_name, path=path)
151
+ dtypes = d.load_dtypes(cl='mysql', db_name=db_name, tabel_name=tabel_name)
301
152
  # 可能会因为没有 json 文件, 返回 None
302
153
  if dtypes:
303
154
  # 按照文件记录更新 dtypes
@@ -306,7 +157,7 @@ class MysqlUpload:
306
157
  col_not_exist = [col for col in cols if col not in dtypes.keys()]
307
158
  # 这些列不存在于 df 中, 必须移除
308
159
  [dtypes.pop(col) for col in list(dtypes.keys()) if col not in cols]
309
- else:
160
+ else: # 没有 json 文件时
310
161
  dtypes = df.dtypes.apply(str).to_dict() # 将 dataframe 数据类型转为字典形式
311
162
  col_not_exist = cols
312
163
  # 对文件不存在的列信息进行数据类型转换(按指定规则)
@@ -347,55 +198,6 @@ class MysqlUpload:
347
198
  else:
348
199
  return 'mediumtext'
349
200
 
350
- def upload_pandas(self, update_path, db_name, days=None):
351
- """
352
- 专门用来上传 pandas数据源的全部文件, 跳过 '其他数据' or '京东数据集'
353
- db_name: 数据库名: pandas数据源
354
- update_path: pandas数据源所在路径
355
- days: 更新近期数据,单位: 天, 不设置则全部更新
356
- """
357
- if days:
358
- today = datetime.date.today()
359
- start_date = pd.to_datetime(today - datetime.timedelta(days=days))
360
- else:
361
- start_date = pd.to_datetime('2000-01-01')
362
-
363
- root_files = os.listdir(update_path)
364
- for root_file in root_files:
365
- if '其他数据' in root_file or '年.csv' in root_file or '京东数据集' in root_file:
366
- continue # 跳过的文件夹
367
- f_path = os.path.join(update_path, root_file)
368
-
369
- if os.path.isdir(f_path):
370
- for root, dirs, files in os.walk(f_path, topdown=False):
371
- for name in files:
372
- if name.endswith('.csv') and 'baidu' not in name:
373
- df = pd.read_csv(os.path.join(root, name), encoding='utf-8_sig', header=0, na_filter=False)
374
- # if '日期' not in df.columns.tolist():
375
- # now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S ")
376
- # print(f'{now}{root_file} 缺少日期列, 不支持上传 mysql')
377
- # continue
378
- if '日期' in df.columns.tolist():
379
- df['日期'] = df['日期'].apply(lambda x: pd.to_datetime(x) if x else x)
380
- df = df[df['日期'] >= start_date]
381
- if len(df) == 0:
382
- continue
383
- self.df_to_mysql(df=df, db_name=db_name, tabel_name=root_file)
384
- elif os.path.isfile(f_path):
385
- if f_path.endswith('.csv') and 'baidu' not in f_path:
386
- df = pd.read_csv(f_path, encoding='utf-8_sig', header=0, na_filter=False)
387
- # if '日期' not in df.columns.tolist():
388
- # now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S ")
389
- # print(f'{now}{root_file} 缺少日期列, 不支持上传 mysql')
390
- # continue
391
- if '日期' not in df.columns.tolist():
392
- df['日期'] = df['日期'].apply(lambda x: pd.to_datetime(x) if x else x)
393
- df = df[df['日期'] >= start_date]
394
- if len(df) == 0:
395
- continue
396
- table = f'{os.path.splitext(root_file)[0]}_f' # 这里定义了文件表会加 _f 后缀
397
- self.df_to_mysql(df=df, db_name=db_name, tabel_name=table)
398
-
399
201
  # @try_except
400
202
  def read_mysql(self, tabel_name, start_date, end_date, db_name='远程数据源', ):
401
203
  start_date = pd.to_datetime(start_date).strftime('%Y-%m-%d')
@@ -446,6 +248,55 @@ class MysqlUpload:
446
248
  print(f'{now}mysql ({self.host}) 表: {tabel_name} 获取数据长度: {len(df)}, 用时: {cost_time} 秒')
447
249
  return df
448
250
 
251
+ def upload_pandas(self, update_path, db_name, days=None):
252
+ """
253
+ 专门用来上传 pandas数据源的全部文件, 跳过 '其他数据' or '京东数据集'
254
+ db_name: 数据库名: pandas数据源
255
+ update_path: pandas数据源所在路径
256
+ days: 更新近期数据,单位: 天, 不设置则全部更新
257
+ """
258
+ if days:
259
+ today = datetime.date.today()
260
+ start_date = pd.to_datetime(today - datetime.timedelta(days=days))
261
+ else:
262
+ start_date = pd.to_datetime('2000-01-01')
263
+
264
+ root_files = os.listdir(update_path)
265
+ for root_file in root_files:
266
+ if '其他数据' in root_file or '年.csv' in root_file or '京东数据集' in root_file:
267
+ continue # 跳过的文件夹
268
+ f_path = os.path.join(update_path, root_file)
269
+
270
+ if os.path.isdir(f_path):
271
+ for root, dirs, files in os.walk(f_path, topdown=False):
272
+ for name in files:
273
+ if name.endswith('.csv') and 'baidu' not in name:
274
+ df = pd.read_csv(os.path.join(root, name), encoding='utf-8_sig', header=0, na_filter=False)
275
+ # if '日期' not in df.columns.tolist():
276
+ # now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S ")
277
+ # print(f'{now}{root_file} 缺少日期列, 不支持上传 mysql')
278
+ # continue
279
+ if '日期' in df.columns.tolist():
280
+ df['日期'] = df['日期'].apply(lambda x: pd.to_datetime(x) if x else x)
281
+ df = df[df['日期'] >= start_date]
282
+ if len(df) == 0:
283
+ continue
284
+ self.df_to_mysql(df=df, db_name=db_name, tabel_name=root_file)
285
+ elif os.path.isfile(f_path):
286
+ if f_path.endswith('.csv') and 'baidu' not in f_path:
287
+ df = pd.read_csv(f_path, encoding='utf-8_sig', header=0, na_filter=False)
288
+ # if '日期' not in df.columns.tolist():
289
+ # now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S ")
290
+ # print(f'{now}{root_file} 缺少日期列, 不支持上传 mysql')
291
+ # continue
292
+ if '日期' not in df.columns.tolist():
293
+ df['日期'] = df['日期'].apply(lambda x: pd.to_datetime(x) if x else x)
294
+ df = df[df['日期'] >= start_date]
295
+ if len(df) == 0:
296
+ continue
297
+ table = f'{os.path.splitext(root_file)[0]}_f' # 这里定义了文件表会加 _f 后缀
298
+ self.df_to_mysql(df=df, db_name=db_name, tabel_name=table)
299
+
449
300
 
450
301
  class OptimizeDatas:
451
302
  """
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: mdbq
3
- Version: 0.4.6
3
+ Version: 1.0.0
4
4
  Home-page: https://pypi.org/project/mdbsql
5
5
  Author: xigua,
6
6
  Author-email: 2587125111@qq.com
@@ -8,6 +8,8 @@ mdbq.egg-info/dependency_links.txt
8
8
  mdbq.egg-info/top_level.txt
9
9
  mdbq/aggregation/__init__.py
10
10
  mdbq/aggregation/aggregation.py
11
+ mdbq/aggregation/df_types.py
12
+ mdbq/aggregation/mysql_types.py
11
13
  mdbq/aggregation/optimize_data.py
12
14
  mdbq/aggregation/query_data.py
13
15
  mdbq/bdup/__init__.py
@@ -28,7 +30,7 @@ mdbq/log/mylogger.py
28
30
  mdbq/mongo/__init__.py
29
31
  mdbq/mongo/mongo.py
30
32
  mdbq/mysql/__init__.py
31
- mdbq/mysql/data_types.py
33
+ mdbq/mysql/data_types_即将删除.py
32
34
  mdbq/mysql/mysql.py
33
35
  mdbq/mysql/s_query.py
34
36
  mdbq/mysql/year_month_day.py
@@ -3,7 +3,7 @@
3
3
  from setuptools import setup, find_packages
4
4
 
5
5
  setup(name='mdbq',
6
- version='0.4.6',
6
+ version='1.0.0',
7
7
  author='xigua, ',
8
8
  author_email="2587125111@qq.com",
9
9
  url='https://pypi.org/project/mdbsql',
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes