mdbq 1.2.3__py3-none-any.whl → 1.2.4__py3-none-any.whl

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.
@@ -930,7 +930,7 @@ def one_file_to_mysql(file, db_name, table_name, target_service, database):
930
930
  filename = os.path.basename(file)
931
931
  df = pd.read_csv(file, encoding='utf-8_sig', header=0, na_filter=False, float_precision='high')
932
932
  m = mysql.MysqlUpload(username=username, password=password, host=host, port=port)
933
- m.df_to_mysql(df=df, db_name=db_name, table_name=table_name, filename=filename)
933
+ m.df_to_mysql(df=df, db_name=db_name, table_name=table_name, filename=filename, df_sql=True)
934
934
 
935
935
 
936
936
  def file_dir(one_file=True):
@@ -975,6 +975,7 @@ def file_dir(one_file=True):
975
975
  path=os.path.join(path, sub_path),
976
976
  db_name = db_name,
977
977
  collection_name = table_name,
978
+ dbs={'mysql': True, 'mongodb': True},
978
979
  )
979
980
  data.update({'入库进度': 1}) # 更新进度为已上传
980
981
  # 将进度信息写回文件
@@ -1000,9 +1001,9 @@ if __name__ == '__main__':
1000
1001
  # print(username, password, host, port)
1001
1002
  file_dir(one_file=False)
1002
1003
  # one_file_to_mysql(
1003
- # file='',
1004
+ # file='/Users/xigua/数据中心/原始文件2/京东报表/商品信息导出/spu/京东商品信息_批量SPU导出-批量任务_2024-08-10.csv',
1004
1005
  # db_name='京东数据2',
1005
- # table_name='商品词下排名',
1006
+ # table_name='京东spu商品信息',
1006
1007
  # target_service='home_lx',
1007
1008
  # database='mysql'
1008
1009
  # )
@@ -206,6 +206,7 @@ def mysql_all_dtypes(db_name=None, table_name=None, path=None):
206
206
  time.sleep(0.5)
207
207
 
208
208
  d = DataTypes()
209
+ d.json_file = os.path.join(path, 'mysql_types.json') # # json 保存位置
209
210
  for result in results:
210
211
  for db_n, table_n in result.items():
211
212
  # print(db_n, table_n, db_name, table_name)
@@ -230,7 +231,7 @@ def mysql_all_dtypes(db_name=None, table_name=None, path=None):
230
231
  cl='mysql',
231
232
  db_name=db_n,
232
233
  table_name=table_n,
233
- is_file_dtype=True
234
+ is_file_dtype=True # True表示旧文件有限
234
235
  )
235
236
  else:
236
237
  print(f'数据库回传数据(name_type)为空')
@@ -239,4 +240,7 @@ def mysql_all_dtypes(db_name=None, table_name=None, path=None):
239
240
 
240
241
 
241
242
  if __name__ == '__main__':
242
- mysql_all_dtypes() # 更新 mysql 中所有数据库的 dtypes 信息到本地 json
243
+ # 更新 mysql 中所有数据库的 dtypes 信息到本地 json
244
+ mysql_all_dtypes(
245
+ path='/Users/xigua/Downloads',
246
+ )
@@ -43,11 +43,14 @@ class DataFrameConverter(object):
43
43
  df[col] = df[col].apply(lambda x: float(float((str(x).rstrip("%"))) / 100) if str(x).endswith('%') and '~' not in str(x) else x)
44
44
  # 尝试转换合适的数据类型
45
45
  if df[col].dtype == 'object':
46
+ # "_"符号会被错误识别
46
47
  try:
47
- df[col] = df[col].apply(lambda x: int(x) if '_' not in str(x) else x)
48
+ df[col] = df[col].apply(lambda x: int(x) if '_' not in str(x) and '.' not in str(x) else x) # 不含小数点尝试转整数
48
49
  except:
50
+ pass
51
+ if df[col].dtype == 'object':
49
52
  try:
50
- df[col] = df[col].apply(lambda x: float(x) if '_' not in str(x) else x)
53
+ df[col] = df[col].apply(lambda x: float(x) if '.' in str(x) and '_' not in str(x) else x)
51
54
  except:
52
55
  pass
53
56
  if df[col].dtype == 'float' or df[col].dtype == 'float64': # 对于小数类型, 保留 6 位小数
mdbq/mysql/mysql.py CHANGED
@@ -9,7 +9,9 @@ import warnings
9
9
  import pymysql
10
10
  import numpy as np
11
11
  import pandas as pd
12
+ import sqlalchemy.types
12
13
  from more_itertools.more import iequals
14
+ from pandas.core.dtypes.common import INT64_DTYPE
13
15
  from sqlalchemy import create_engine
14
16
  import os
15
17
  import calendar
@@ -20,19 +22,20 @@ from mdbq.aggregation import mysql_types
20
22
 
21
23
  warnings.filterwarnings('ignore')
22
24
  """
23
- 建表规范:
25
+ 建表流程:
24
26
  尽可能手动建表,再上传数据
25
- 1. 先建 json 表,再批量上传数据;(非常重要)
26
- 在初创数据表时, 如果有不同类报表,新版和旧版都要取一个文件,先创建数据表,再导其他数据;
27
- 例如有的报表转化率是0%,数据类型会被识别为2位小数: decimal(10, 2),正常值应类似 0.43%,应保留4个小数, 创建类型为 decimal(10, 4)
28
- 为了避免以上可能数据类型错误的情况,初创时要先检查一遍数据类型,确认没问题再导其他数据!
29
- 即导一个表,然后删除数据库,但保留 mysql_types.json,并检查表的数据类型(有问题就手动改 json 文件),之后会按 json 的 types 上传数据;
27
+ 1. 每个表手动上传一个文件建表
28
+ 2. 全部建表完成,建议所有表的数据类型,有问题的在数据库修改
29
+ 3. 清空所有数据表,仅保留列信息
30
+ 4. 下载所有数据表的 dtypes 信息到 json 文件
31
+ 5. 之后可以正常上传数据
30
32
 
31
- 2. 数据库和数据表名如果有字母,必须使用小写,大写在建库后会自动变小写,再次上传数据会找不到数据库(macos和linux都有这种情况)
32
- 3. 无论是数据库/表/列名还是值,尽量避免特殊字符或者表情符号,数据库/表/列名尽量都使用 `列名` 转义,避免错误
33
- 4. 小数必须使用 decimal, 禁止 float 和 double, 因为计算精度差异,后续需要聚合数据时会引发很多问题
34
- 5. 日期类型暂时全部用 DATETIME,使用 DATE 在后续可能会重复插入不能排重,因为 df 进来的数据, 日期是带时间的,而数据库中日期不含时间
35
- 6. 目前小数自动适配类型转换,对于文本或者大数全部用 mediumtext, 因为部分表涉及爬虫数据,进来的字符长度未知,暂时统一 mediumtext 避免入库失败
33
+ 建表规范:
34
+ 1. 数据库和数据表名如果有字母,必须使用小写,大写在建库后会自动变小写,再次上传数据会找不到数据库(macos和linux都有这种情况)
35
+ 2. 无论是数据库/表/列名还是值,尽量避免特殊字符或者表情符号,数据库/表/列名尽量都使用 `列名` 转义,避免错误
36
+ 3. 小数必须使用 decimal, 禁止 float double, 因为计算精度差异,后续需要聚合数据时会引发很多问题
37
+ 4. 日期类型暂时全部用 DATETIME,使用 DATE 在后续可能会重复插入不能排重,因为 df 进来的数据, 日期是带时间的,而数据库中日期不含时间
38
+ 5. 目前小数自动适配类型转换,对于文本或者大数全部用 mediumtext, 因为部分表涉及爬虫数据,进来的字符长度未知,暂时统一 mediumtext 避免入库失败
36
39
 
37
40
 
38
41
 
@@ -57,7 +60,7 @@ class MysqlUpload:
57
60
  }
58
61
  self.filename = None
59
62
 
60
- def df_to_mysql(self, df, table_name, db_name='远程数据源', drop_dup=True, drop_duplicates=False, filename=None, count=None):
63
+ def df_to_mysql(self, df, table_name, db_name='远程数据源', df_sql=False, drop_dup=True, drop_duplicates=False, filename=None, count=None):
61
64
  """
62
65
  将 df 写入数据库
63
66
  db_name: 数据库名称
@@ -74,9 +77,23 @@ class MysqlUpload:
74
77
  else:
75
78
  print(f'{db_name}: {table_name} 传入的 df 不是有效的 dataframe 结构, {self.filename}')
76
79
  return
80
+
77
81
  cv = converter.DataFrameConverter()
78
82
  df = cv.convert_df_cols(df=df) # 清理 dataframe 非法值
79
83
 
84
+ # if df_sql:
85
+ # now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S ")
86
+ # print(f'{now}正在更新 mysql ({self.host}:{self.port}) {db_name}/{table_name}, {count},{self.filename}')
87
+ # engine = create_engine(f"mysql+pymysql://{self.username}:{self.password}@{self.host}:{self.port}/{db_name}") # 创建数据库引擎
88
+ # df.to_sql(
89
+ # name=table_name,
90
+ # con=engine,
91
+ # if_exists='append',
92
+ # index=False,
93
+ # chunksize=1000,
94
+ # dtype={'京东价': 'INT'},
95
+ # )
96
+ # return
80
97
  connection = pymysql.connect(**self.config) # 连接数据库
81
98
  with connection.cursor() as cursor:
82
99
  cursor.execute(f"SHOW DATABASES LIKE '{db_name}'") # 检查数据库是否存在
@@ -133,6 +150,21 @@ class MysqlUpload:
133
150
  print(f'{self.filename}: {e}')
134
151
  connection.commit() # 提交事务
135
152
 
153
+ if df_sql:
154
+ now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S ")
155
+ print(f'{now}正在更新 mysql ({self.host}:{self.port}) {db_name}/{table_name}, {count},{self.filename}')
156
+ engine = create_engine(
157
+ f"mysql+pymysql://{self.username}:{self.password}@{self.host}:{self.port}/{db_name}") # 创建数据库引擎
158
+ df.to_sql(
159
+ name=table_name,
160
+ con=engine,
161
+ if_exists='append',
162
+ index=False,
163
+ chunksize=1000
164
+ )
165
+ connection.close()
166
+ return
167
+
136
168
  # print(cl, db_n, tb_n)
137
169
  # 返回这些结果的目的是等添加完列再写 json 文件才能读到 types 信息
138
170
  if cl and db_n and tb_n:
@@ -154,6 +186,7 @@ class MysqlUpload:
154
186
  # 5. 更新插入数据
155
187
  now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S ")
156
188
  print(f'{now}正在更新 mysql ({self.host}:{self.port}) {db_name}/{table_name}, {count},{self.filename}')
189
+
157
190
  datas = df.to_dict(orient='records')
158
191
  for data in datas:
159
192
  try:
@@ -185,6 +218,7 @@ class MysqlUpload:
185
218
  print(f'mysql -> df_to_mysql 报错: {e}, {self.filename}')
186
219
  # breakpoint()
187
220
  connection.commit() # 提交事务
221
+ connection.close()
188
222
 
189
223
  def convert_dtypes(self, df, db_name, table_name):
190
224
  """
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: mdbq
3
- Version: 1.2.3
3
+ Version: 1.2.4
4
4
  Home-page: https://pypi.org/project/mdbsql
5
5
  Author: xigua,
6
6
  Author-email: 2587125111@qq.com
@@ -1,9 +1,9 @@
1
1
  mdbq/__init__.py,sha256=Il5Q9ATdX8yXqVxtP_nYqUhExzxPC_qk_WXQ_4h0exg,16
2
2
  mdbq/__version__.py,sha256=y9Mp_8x0BCZSHsdLT_q5tX9wZwd5QgqrSIENLrb6vXA,62
3
3
  mdbq/aggregation/__init__.py,sha256=EeDqX2Aml6SPx8363J-v1lz0EcZtgwIBYyCJV6CcEDU,40
4
- mdbq/aggregation/aggregation.py,sha256=-TGvWaLUMfPJHeQ3ZsL6WaN2bkA9DHyXWLM-WEMa26Y,57255
4
+ mdbq/aggregation/aggregation.py,sha256=a-lK0R6fEqj5InZZXly-xqfyZ4mCDMqAuEHuTzKMvv0,57467
5
5
  mdbq/aggregation/df_types.py,sha256=rHLIgv82PJSFmDvXkZyOJAffXkFyyMyFO23w9tUt8EQ,7525
6
- mdbq/aggregation/mysql_types.py,sha256=h0BCAY98nzkCwoLCQczPz5cLY1jkU4w84Ovkg7dEu4Y,10477
6
+ mdbq/aggregation/mysql_types.py,sha256=umVixmbFZM63k-QhVWLvOuhcAde4P_oDKbdo8ry2O9w,10633
7
7
  mdbq/aggregation/optimize_data.py,sha256=jLAWtxPUuhpo4XTVrhKtT4xK3grs7r73ePQfLhxlu1I,779
8
8
  mdbq/aggregation/query_data.py,sha256=sdMWj0st_VFDfBHmqTrY05k-0yoagdnaiNMoB0otEuk,25255
9
9
  mdbq/bdup/__init__.py,sha256=AkhsGk81SkG1c8FqDH5tRq-8MZmFobVbN60DTyukYTY,28
@@ -18,14 +18,14 @@ mdbq/config/products.py,sha256=9gqXJMsw8KKuD4Xs6krNgcF7AuWDvV7clI6wVi3QjcA,4260
18
18
  mdbq/config/set_support.py,sha256=xkZCX6y9Bq1ppBpJAofld4B2YtchA7fl0eT3dx3CrSI,777
19
19
  mdbq/config/update_conf.py,sha256=taL3ZqKgiVWwUrDFuaYhim9a72Hm4BHRhhDscJTziR8,4535
20
20
  mdbq/dataframe/__init__.py,sha256=2HtCN8AdRj53teXDqzysC1h8aPL-mMFy561ESmhehGQ,22
21
- mdbq/dataframe/converter.py,sha256=6eVs8Bfj7-SaYksITEF0gZVa0U3eoTIDyFLSPiBwkhM,3400
21
+ mdbq/dataframe/converter.py,sha256=BAst61HvtXqN3yWguia47zNY19c-wpby8CsdS48PC6g,3592
22
22
  mdbq/log/__init__.py,sha256=Mpbrav0s0ifLL7lVDAuePEi1hJKiSHhxcv1byBKDl5E,15
23
23
  mdbq/log/mylogger.py,sha256=oaT7Bp-Hb9jZt52seP3ISUuxVcI19s4UiqTeouScBO0,3258
24
24
  mdbq/mongo/__init__.py,sha256=SILt7xMtQIQl_m-ik9WLtJSXIVf424iYgCfE_tnQFbw,13
25
25
  mdbq/mongo/mongo.py,sha256=v9qvrp6p1ZRWuPpbSilqveiE0FEcZF7U5xUPI0RN4xs,31880
26
26
  mdbq/mysql/__init__.py,sha256=A_DPJyAoEvTSFojiI2e94zP0FKtCkkwKP1kYUCSyQzo,11
27
27
  mdbq/mysql/data_types_即将删除.py,sha256=sjBBDKr9674LdjM5N_dwyJACdZPbdB8Beli59jGdgnQ,10378
28
- mdbq/mysql/mysql.py,sha256=Hj2ymZY15lsPQKCPOA9JMUOwOi8gTBq-LnEsFKW5-BY,36440
28
+ mdbq/mysql/mysql.py,sha256=hZWk7rgoeCkNYbGMgJokiPJSoMJ3y-wSVH_ojzh49l8,37464
29
29
  mdbq/mysql/s_query.py,sha256=4c24SwbqtnO33o8CgWlTQ_j8sZYl5BRIQkaD9CI-vTY,7901
30
30
  mdbq/mysql/year_month_day.py,sha256=VgewoE2pJxK7ErjfviL_SMTN77ki8GVbTUcao3vFUCE,1523
31
31
  mdbq/other/__init__.py,sha256=jso1oHcy6cJEfa7udS_9uO5X6kZLoPBF8l3wCYmr5dM,18
@@ -36,7 +36,7 @@ mdbq/pbix/__init__.py,sha256=Trtfaynu9RjoTyLLYBN2xdRxTvm_zhCniUkVTAYwcjo,24
36
36
  mdbq/pbix/pbix_refresh.py,sha256=JUjKW3bNEyoMVfVfo77UhguvS5AWkixvVhDbw4_MHco,2396
37
37
  mdbq/pbix/refresh_all.py,sha256=tgy762608HMaXWynbOURIf2UVMuSPybzrDXQnOOcnZU,6102
38
38
  mdbq/spider/__init__.py,sha256=RBMFXGy_jd1HXZhngB2T2XTvJqki8P_Fr-pBcwijnew,18
39
- mdbq-1.2.3.dist-info/METADATA,sha256=6nMtIPxpdSxm_Ws6LOo_EaoOkmfll2lYwrdLDsQ0RSU,245
40
- mdbq-1.2.3.dist-info/WHEEL,sha256=eOLhNAGa2EW3wWl_TU484h7q1UNgy0JXjjoqKoxAAQc,92
41
- mdbq-1.2.3.dist-info/top_level.txt,sha256=2FQ-uLnCSB-OwFiWntzmwosW3X2Xqsg0ewh1axsaylA,5
42
- mdbq-1.2.3.dist-info/RECORD,,
39
+ mdbq-1.2.4.dist-info/METADATA,sha256=ekCyUS5vKgOSEK7iYzdo-70H1ThaVi89ATDo6jnJBSI,245
40
+ mdbq-1.2.4.dist-info/WHEEL,sha256=eOLhNAGa2EW3wWl_TU484h7q1UNgy0JXjjoqKoxAAQc,92
41
+ mdbq-1.2.4.dist-info/top_level.txt,sha256=2FQ-uLnCSB-OwFiWntzmwosW3X2Xqsg0ewh1axsaylA,5
42
+ mdbq-1.2.4.dist-info/RECORD,,
File without changes