mdbq 1.5.5__py3-none-any.whl → 1.5.7__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.
mdbq/config/get_myconf.py CHANGED
@@ -21,7 +21,7 @@ class MyConf:
21
21
 
22
22
  def get_myconf(self, options: list):
23
23
  if not os.path.exists(self.conf_file):
24
- print(f'尚未配置: 缺少 .my_conf 文件')
24
+ print(f'尚未配置: 缺少 .my_conf 文件 {self.conf_file}')
25
25
  return
26
26
  if not options:
27
27
  print(f'传入的参数为空: {options}')
@@ -0,0 +1,131 @@
1
+ # -*- coding: UTF-8 –*-
2
+ import platform
3
+ import getpass
4
+ import socket
5
+ import configparser
6
+ import os
7
+ import sys
8
+ from posixpath import dirname
9
+ from urllib import parse
10
+ from mdbq.config import set_support
11
+
12
+
13
+ class MyConf:
14
+ """
15
+ 读取配置文件信息
16
+ """
17
+ def __init__(self, path='support'):
18
+ self.top_path = os.path.realpath(os.path.dirname(sys.argv[0])) # 程序运行目录, 打包时使用
19
+ self.conf_file = os.path.join(self.top_path, path, '.my_conf')
20
+ self.config = None
21
+
22
+ def get_myconf(self, options: list):
23
+ if not os.path.exists(self.conf_file):
24
+ print(f'尚未配置: 缺少 .my_conf 文件')
25
+ return
26
+ if not options:
27
+ print(f'传入的参数为空: {options}')
28
+ return
29
+ self.config = configparser.ConfigParser()
30
+ self.config.read(self.conf_file, 'UTF-8')
31
+ results = []
32
+ for option in options:
33
+ try:
34
+ results.append(self.config.get('database', option))
35
+ except configparser.NoOptionError:
36
+ results.append('')
37
+ return results
38
+
39
+
40
+ def select_config_values(target_service, database, path=None):
41
+ """
42
+ target_service: 指向: home_lx, aliyun
43
+ database: 指向: mongodb, mysql
44
+ """
45
+ if not path:
46
+ path = set_support.SetSupport(dirname='support').dirname
47
+
48
+ m = MyConf(path=path)
49
+ options = []
50
+ if target_service == 'home_lx': # 1. 家里笔记本
51
+ if database == 'mongodb':
52
+ if socket.gethostname() == 'xigua_lx':
53
+ # 本机自身运行使用 127.0.0.1
54
+ options = ['username_db_lx_nw', 'password_db_lx_nw', 'host_bd', 'port_db_lx_nw',]
55
+ elif socket.gethostname() == 'xigua1' or socket.gethostname() == 'MacBook-Pro':
56
+ # 内网地址:正在运行的是 家里笔记本或者台式机,或者 macbook pro
57
+ options = ['username_db_lx_nw', 'password_db_lx_nw', 'host_db_lx_nw', 'port_db_lx_nw',]
58
+ else:
59
+ options = ['username_db_lx', 'password_db_lx', 'host_db_lx', 'port_db_lx']
60
+
61
+ elif database == 'mysql':
62
+ if socket.gethostname() == 'xigua_lx':
63
+ # 本机自身运行使用 127.0.0.1
64
+ options = ['username_mysql_lx_nw', 'password_mysql_lx_nw', 'host_bd', 'port_mysql_lx_nw',]
65
+ elif socket.gethostname() == 'xigua1' or socket.gethostname() == 'MacBook-Pro':
66
+ # 内网地址:正在运行的是 家里笔记本或者台式机,或者 macb ook pro
67
+ options = ['username_mysql_lx_nw', 'password_mysql_lx_nw', 'host_mysql_lx_nw', 'port_mysql_lx_nw',]
68
+ else:
69
+ options = ['username_mysql_lx', 'password_mysql_lx', 'host_mysql_lx', 'port_mysql_lx']
70
+
71
+ elif target_service == 'home_xigua1':
72
+ if database == 'mongodb':
73
+ print('未配置')
74
+ elif database == 'mysql':
75
+ if socket.gethostname() == 'xigua_lx':
76
+ # 本机自身运行使用 127.0.0.1
77
+ options = ['username_mysql_xigua1_nw', 'password_mysql_xigua1_nw', 'host_mysql_xigua1_nw', 'port_mysql_xigua1_nw',]
78
+ elif socket.gethostname() == 'xigua1' or socket.gethostname() == 'macbook pro':
79
+ # 内网地址:正在运行的是 家里笔记本或者台式机,或者 macb ook pro
80
+ options = ['username_mysql_xigua1_nw', 'password_mysql_xigua1_nw', 'host_bd', 'port_mysql_xigua1_nw',]
81
+ else:
82
+ print('未配置')
83
+ options = ['', '', '', '']
84
+
85
+ elif target_service == 'aliyun': # 2. 阿里云服务器
86
+ if database == 'mongodb':
87
+ if socket.gethostname() == 'xigua-cloud':
88
+ # 阿里云自身运行使用 127.0.0.1
89
+ options = ['username_db_aliyun', 'password_db_aliyun', 'host_bd', 'port_db_aliyun', ]
90
+ else:
91
+ options = ['username_db_aliyun', 'password_db_aliyun', 'host_db_aliyun', 'port_db_aliyun', ]
92
+ elif database == 'mysql':
93
+ if socket.gethostname() == 'xigua-cloud':
94
+ # 阿里云自身运行使用 127.0.0.1
95
+ options = ['username_mysql_aliyun', 'password_mysql_aliyun', 'host_bd', 'port_mysql_aliyun', ]
96
+ else:
97
+ options = ['username_mysql_aliyun', 'password_mysql_aliyun', 'host_mysql_aliyun', 'port_mysql_aliyun', ]
98
+
99
+ elif target_service == 'company': # 3. 公司台式机
100
+ if database == 'mongodb':
101
+ options = ['username_db_company_nw', 'password_db_company_nw', 'host_db_company_nw', 'port_db_company_nw', ]
102
+ elif database == 'mysql':
103
+ options = ['username_mysql_company_nw', 'password_mysql_company_nw', 'host_mysql_company_nw', 'port_mysql_company_nw', ]
104
+
105
+ elif target_service == 'nas': # 4. 群晖
106
+ if database == 'mysql':
107
+ options = ['username_mysql_nas_nw', 'password_mysql_nas_nw', 'host_mysql_nas_nw', 'port_mysql_nas_nw', ]
108
+
109
+ value = m.get_myconf(options=options)
110
+ if not value:
111
+ return '', '', '', 0
112
+ if database == 'mongodb': # mongodb 特殊字符要转码, mysql 不需要转
113
+ username = parse.quote_plus(str(value[0]).strip()) # 对可能存在的特殊字符进行编码
114
+ password = parse.quote_plus(str(value[1]).strip()) # 如果密码含有 @、/ 字符,一定要进行编码
115
+ else:
116
+ username = str(value[0]).strip()
117
+ password = str(value[1]).strip()
118
+ host = str(value[2]).strip()
119
+ port = int(value[3])
120
+ return username, password, host, port
121
+
122
+
123
+ def main():
124
+ pass
125
+
126
+
127
+ if __name__ == '__main__':
128
+ # main()
129
+ r, d, s, g = select_config_values(target_service='home_lx', database='mysql')
130
+ print(r, d, s, g, type(r), type(d), type(s), type(g))
131
+ print(f'本机: {platform.system()} // {socket.gethostname()}')
mdbq/mysql/mysql.py CHANGED
@@ -180,87 +180,87 @@ class MysqlUpload:
180
180
  for data in datas:
181
181
  # data 是传进来待处理的数据, 不是数据库数据
182
182
  # data 示例: {'日期': Timestamp('2024-08-27 00:00:00'), '推广费余额': 33299, '品销宝余额': 2930.73, '短信剩余': 67471}
183
- # try:
184
- cols = ', '.join(f"`{item}`" for item in data.keys()) # 列名需要转义
185
- # data.update({item: f"{data[item]}" for item in data.keys()}) # 全部值转字符, 不是必须的
186
- values = ', '.join([f'"{item}"' for item in data.values()]) # 值要加引号
187
- condition = []
188
- for k, v in data.items():
189
- condition += [f'`{k}` = "{v}"']
190
- condition = ' AND '.join(condition) # 构建查询条件
191
- # print(condition)
192
-
193
- if drop_duplicates: # 查重插入
194
- sql = "SELECT %s FROM %s WHERE %s" % (cols, table_name, condition)
195
- # sql = f"SELECT {cols} FROM `{table_name}` WHERE `创建时间` = '2014-09-19 14:32:33'"
196
- # print(sql)
197
- cursor.execute(sql)
198
- result = cursor.fetchall() # 获取查询结果, 有结果返回 list 表示数据已存在(不重复插入),没有则返回空 tuple
199
- if not result: # 数据不存在则插入
200
- sql = f"INSERT INTO `{table_name}` ({cols}) VALUES (%s);" % (values)
201
- cursor.execute(sql)
202
- # else:
203
- # print(f'重复数据不插入: {condition[:50]}...')
204
- elif icm_update: # 增量更新, 专门用于聚合数据,其他库不要调用
205
- """ 使用增量更新: 需确保 icm_update['主键'] 传进来的列必须是数据表中唯一主键,值不会发生变化且不会重复,否则可能产生覆盖情况 """
206
- sql = 'SELECT COLUMN_NAME FROM information_schema.columns WHERE table_schema = %s AND table_name = %s'
207
- cursor.execute(sql, (db_name, {table_name}))
208
- columns = cursor.fetchall()
209
- cols_exist = [col['COLUMN_NAME'] for col in columns] # 数据表的所有列, 返回 list
210
- update_col = [item for item in cols_exist if item not in icm_update and item != 'id'] # 除了主键外的其他列
211
-
212
- # unique_keys 示例: `日期`, `推广费余额`
213
- unique_keys = ', '.join(f"`{item}`" for item in update_col) # 列名需要转义
183
+ try:
184
+ cols = ', '.join(f"`{item}`" for item in data.keys()) # 列名需要转义
185
+ # data.update({item: f"{data[item]}" for item in data.keys()}) # 全部值转字符, 不是必须的
186
+ values = ', '.join([f'"{item}"' for item in data.values()]) # 值要加引号
214
187
  condition = []
215
- for up_col in icm_update:
216
- condition += [f'`{up_col}` = "{data[up_col]}"']
217
- condition = ' AND '.join(condition) # condition值示例: `品销宝余额` = '2930.73' AND `短信剩余` = '67471'
218
- sql = f"SELECT {unique_keys} FROM `{table_name}` WHERE {condition}"
219
- # print(sql)
220
- # sql = f"SELECT {unique_keys} FROM `{table_name}` WHERE `创建时间` = '2014-09-19 14:32:33'"
221
- cursor.execute(sql)
222
- results = cursor.fetchall() # results 是数据库取出的数据
223
- if results: # 有数据返回,再进行增量检查
224
- for result in results: # results 是数据库数据, data 是传进来的数据
225
- change_col = [] # 发生变化的列名
226
- change_values = [] # 发生变化的数据
227
- for col in update_col:
228
- # 因为 mysql 里面有 decimal 数据类型,要移除末尾的 0 再做比较(df 默认将 5.00 小数截断为 5.0)
229
- df_value = str(data[col])
230
- mysql_value = str(result[col])
231
- if '.' in df_value:
232
- df_value = re.sub(r'0+$', '', df_value)
233
- df_value = re.sub(r'\.$', '', df_value)
234
- if '.' in mysql_value:
235
- mysql_value = re.sub(r'0+$', '', mysql_value)
236
- mysql_value = re.sub(r'\.$', '', mysql_value)
237
- if df_value != mysql_value: # 传进来的数据和数据库比较, 有变化
238
- # print(f'{data['日期']}{data['商品id']}{col} 列的值有变化,{str(data[col])} != {str(result[col])}')
239
- change_values += [f"`{col}` = \"{str(data[col])}\""]
240
- change_col.append(col)
241
- not_change_col = [item for item in update_col if item not in change_col]
242
- # change_values 是 df 传进来且和数据库对比后,发生了变化的数据,值示例: [`品销宝余额` = '9999.0', `短信剩余` = '888']
243
- if change_values: # change_values 有数据返回,表示值需要更新
244
- if not_change_col:
245
- not_change_values = [f'`{col}` = "{str(data[col])}"' for col in not_change_col]
246
- not_change_values = ' AND '.join(not_change_values) # 示例: `短信剩余` = '888' AND `test1` = '93'
247
- # print(change_values, not_change_values)
248
- condition += f' AND {not_change_values}' # 重新构建完整的查询条件,将未发生变化的列加进查询条件
249
- change_values = ', '.join(f"{item}" for item in change_values) # 注意这里 item 外面没有反引号
250
- sql = "UPDATE `%s` SET %s WHERE %s" % (table_name, change_values, condition)
251
- # print(sql)
252
- cursor.execute(sql)
253
- else: # 没有数据返回,则直接插入数据
254
- sql = f"INSERT INTO `{table_name}` ({cols}) VALUES ({values});"
188
+ for k, v in data.items():
189
+ condition += [f'`{k}` = "{v}"']
190
+ condition = ' AND '.join(condition) # 构建查询条件
191
+ # print(condition)
192
+
193
+ if drop_duplicates: # 查重插入
194
+ sql = "SELECT %s FROM %s WHERE %s" % (cols, table_name, condition)
195
+ # sql = f"SELECT {cols} FROM `{table_name}` WHERE `创建时间` = '2014-09-19 14:32:33'"
196
+ # print(sql)
255
197
  cursor.execute(sql)
256
- else:
257
- sql = f"INSERT INTO `{table_name}` ({cols}) VALUES (%s);" % (values)
258
- cursor.execute(sql)
259
- # except Exception as e:
260
- # # print(data)
261
- # # print(values)
262
- # print(f'mysql -> df_to_mysql 报错: {e}, {self.filename}')
263
- # # breakpoint()
198
+ result = cursor.fetchall() # 获取查询结果, 有结果返回 list 表示数据已存在(不重复插入),没有则返回空 tuple
199
+ if not result: # 数据不存在则插入
200
+ sql = f"INSERT INTO `{table_name}` ({cols}) VALUES (%s);" % (values)
201
+ cursor.execute(sql)
202
+ # else:
203
+ # print(f'重复数据不插入: {condition[:50]}...')
204
+ elif icm_update: # 增量更新, 专门用于聚合数据,其他库不要调用
205
+ """ 使用增量更新: 需确保 icm_update['主键'] 传进来的列必须是数据表中唯一主键,值不会发生变化且不会重复,否则可能产生覆盖情况 """
206
+ sql = 'SELECT COLUMN_NAME FROM information_schema.columns WHERE table_schema = %s AND table_name = %s'
207
+ cursor.execute(sql, (db_name, {table_name}))
208
+ columns = cursor.fetchall()
209
+ cols_exist = [col['COLUMN_NAME'] for col in columns] # 数据表的所有列, 返回 list
210
+ update_col = [item for item in cols_exist if item not in icm_update and item != 'id'] # 除了主键外的其他列
211
+
212
+ # unique_keys 示例: `日期`, `推广费余额`
213
+ unique_keys = ', '.join(f"`{item}`" for item in update_col) # 列名需要转义
214
+ condition = []
215
+ for up_col in icm_update:
216
+ condition += [f'`{up_col}` = "{data[up_col]}"']
217
+ condition = ' AND '.join(condition) # condition值示例: `品销宝余额` = '2930.73' AND `短信剩余` = '67471'
218
+ sql = f"SELECT {unique_keys} FROM `{table_name}` WHERE {condition}"
219
+ # print(sql)
220
+ # sql = f"SELECT {unique_keys} FROM `{table_name}` WHERE `创建时间` = '2014-09-19 14:32:33'"
221
+ cursor.execute(sql)
222
+ results = cursor.fetchall() # results 是数据库取出的数据
223
+ if results: # 有数据返回,再进行增量检查
224
+ for result in results: # results 是数据库数据, data 是传进来的数据
225
+ change_col = [] # 发生变化的列名
226
+ change_values = [] # 发生变化的数据
227
+ for col in update_col:
228
+ # 因为 mysql 里面有 decimal 数据类型,要移除末尾的 0 再做比较(df 默认将 5.00 小数截断为 5.0)
229
+ df_value = str(data[col])
230
+ mysql_value = str(result[col])
231
+ if '.' in df_value:
232
+ df_value = re.sub(r'0+$', '', df_value)
233
+ df_value = re.sub(r'\.$', '', df_value)
234
+ if '.' in mysql_value:
235
+ mysql_value = re.sub(r'0+$', '', mysql_value)
236
+ mysql_value = re.sub(r'\.$', '', mysql_value)
237
+ if df_value != mysql_value: # 传进来的数据和数据库比较, 有变化
238
+ # print(f'{data['日期']}{data['商品id']}{col} 列的值有变化,{str(data[col])} != {str(result[col])}')
239
+ change_values += [f"`{col}` = \"{str(data[col])}\""]
240
+ change_col.append(col)
241
+ not_change_col = [item for item in update_col if item not in change_col]
242
+ # change_values 是 df 传进来且和数据库对比后,发生了变化的数据,值示例: [`品销宝余额` = '9999.0', `短信剩余` = '888']
243
+ if change_values: # change_values 有数据返回,表示值需要更新
244
+ if not_change_col:
245
+ not_change_values = [f'`{col}` = "{str(data[col])}"' for col in not_change_col]
246
+ not_change_values = ' AND '.join(not_change_values) # 示例: `短信剩余` = '888' AND `test1` = '93'
247
+ # print(change_values, not_change_values)
248
+ condition += f' AND {not_change_values}' # 重新构建完整的查询条件,将未发生变化的列加进查询条件
249
+ change_values = ', '.join(f"{item}" for item in change_values) # 注意这里 item 外面没有反引号
250
+ sql = "UPDATE `%s` SET %s WHERE %s" % (table_name, change_values, condition)
251
+ # print(sql)
252
+ cursor.execute(sql)
253
+ else: # 没有数据返回,则直接插入数据
254
+ sql = f"INSERT INTO `{table_name}` ({cols}) VALUES ({values});"
255
+ cursor.execute(sql)
256
+ else:
257
+ sql = f"INSERT INTO `{table_name}` ({cols}) VALUES (%s);" % (values)
258
+ cursor.execute(sql)
259
+ except Exception as e:
260
+ # print(data)
261
+ # print(values)
262
+ print(f'mysql -> df_to_mysql 报错: {e}, {self.filename}')
263
+ # breakpoint()
264
264
  connection.commit() # 提交事务
265
265
  connection.close()
266
266
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: mdbq
3
- Version: 1.5.5
3
+ Version: 1.5.7
4
4
  Home-page: https://pypi.org/project/mdbsql
5
5
  Author: xigua,
6
6
  Author-email: 2587125111@qq.com
@@ -13,7 +13,8 @@ mdbq/clean/data_clean.py,sha256=BIzc1XCJjJaZyPT6DCRXRCCRwBaeC5_lER0aqYF1P3M,8777
13
13
  mdbq/company/__init__.py,sha256=qz8F_GsP_pMB5PblgJAUAMjasuZbOEp3qQOCB39E8f0,21
14
14
  mdbq/company/copysh.py,sha256=WCZ92vCJAy6_ZFeOxWL-U9gArIpyga4xts-s1wKsspY,17268
15
15
  mdbq/config/__init__.py,sha256=jso1oHcy6cJEfa7udS_9uO5X6kZLoPBF8l3wCYmr5dM,18
16
- mdbq/config/get_myconf.py,sha256=bp6bVARZVm3ANj1pmM9hLB8Ao539TUWeM9xxeSsBpzw,5994
16
+ mdbq/config/get_myconf.py,sha256=-CFEW0dQh4OIwVgwK-cL0eVp1LN3PjJgN89d4P5TB9I,6011
17
+ mdbq/config/get_myconf_冲突文件_Administrator_20240901101505.py,sha256=bp6bVARZVm3ANj1pmM9hLB8Ao539TUWeM9xxeSsBpzw,5994
17
18
  mdbq/config/products.py,sha256=vIK8DJ-F3XXwvNPK-4OJq2tZITNlL6Sub8QBdoOng8U,5676
18
19
  mdbq/config/set_support.py,sha256=xkZCX6y9Bq1ppBpJAofld4B2YtchA7fl0eT3dx3CrSI,777
19
20
  mdbq/config/update_conf.py,sha256=taL3ZqKgiVWwUrDFuaYhim9a72Hm4BHRhhDscJTziR8,4535
@@ -24,7 +25,7 @@ mdbq/log/mylogger.py,sha256=oaT7Bp-Hb9jZt52seP3ISUuxVcI19s4UiqTeouScBO0,3258
24
25
  mdbq/mongo/__init__.py,sha256=SILt7xMtQIQl_m-ik9WLtJSXIVf424iYgCfE_tnQFbw,13
25
26
  mdbq/mongo/mongo.py,sha256=v9qvrp6p1ZRWuPpbSilqveiE0FEcZF7U5xUPI0RN4xs,31880
26
27
  mdbq/mysql/__init__.py,sha256=A_DPJyAoEvTSFojiI2e94zP0FKtCkkwKP1kYUCSyQzo,11
27
- mdbq/mysql/mysql.py,sha256=o2QRV3JZ_jva8u3ScFiMGcgnInSGFYfADm1-nEKMr4M,43051
28
+ mdbq/mysql/mysql.py,sha256=6hILGosp2fwTp9qgc9IMFTmNzAz0ZG8rznmPxXHY-eA,43331
28
29
  mdbq/mysql/s_query.py,sha256=a33aYhW6gAnspIZfQ7l23ePln9-MD1f_ukypr5M0jd8,8018
29
30
  mdbq/mysql/year_month_day.py,sha256=VgewoE2pJxK7ErjfviL_SMTN77ki8GVbTUcao3vFUCE,1523
30
31
  mdbq/other/__init__.py,sha256=jso1oHcy6cJEfa7udS_9uO5X6kZLoPBF8l3wCYmr5dM,18
@@ -35,7 +36,7 @@ mdbq/pbix/__init__.py,sha256=Trtfaynu9RjoTyLLYBN2xdRxTvm_zhCniUkVTAYwcjo,24
35
36
  mdbq/pbix/pbix_refresh.py,sha256=JUjKW3bNEyoMVfVfo77UhguvS5AWkixvVhDbw4_MHco,2396
36
37
  mdbq/pbix/refresh_all.py,sha256=tgy762608HMaXWynbOURIf2UVMuSPybzrDXQnOOcnZU,6102
37
38
  mdbq/spider/__init__.py,sha256=RBMFXGy_jd1HXZhngB2T2XTvJqki8P_Fr-pBcwijnew,18
38
- mdbq-1.5.5.dist-info/METADATA,sha256=sojaLXm4UyJOVGaIdmUSed7v7vgOLZWovptcEW_oH5s,245
39
- mdbq-1.5.5.dist-info/WHEEL,sha256=cpQTJ5IWu9CdaPViMhC9YzF8gZuS5-vlfoFihTBC86A,91
40
- mdbq-1.5.5.dist-info/top_level.txt,sha256=2FQ-uLnCSB-OwFiWntzmwosW3X2Xqsg0ewh1axsaylA,5
41
- mdbq-1.5.5.dist-info/RECORD,,
39
+ mdbq-1.5.7.dist-info/METADATA,sha256=jKf6D_Ytp6rJxkjmFn_uMhsXKmR6NiUfoe9I_uwILWA,245
40
+ mdbq-1.5.7.dist-info/WHEEL,sha256=cpQTJ5IWu9CdaPViMhC9YzF8gZuS5-vlfoFihTBC86A,91
41
+ mdbq-1.5.7.dist-info/top_level.txt,sha256=2FQ-uLnCSB-OwFiWntzmwosW3X2Xqsg0ewh1axsaylA,5
42
+ mdbq-1.5.7.dist-info/RECORD,,
File without changes