pyxllib 0.0.43__py3-none-any.whl → 0.3.197__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.
Files changed (186) hide show
  1. pyxllib/__init__.py +9 -2
  2. pyxllib/algo/__init__.py +8 -0
  3. pyxllib/algo/disjoint.py +54 -0
  4. pyxllib/algo/geo.py +541 -0
  5. pyxllib/{util/mathlib.py → algo/intervals.py} +172 -36
  6. pyxllib/algo/matcher.py +389 -0
  7. pyxllib/algo/newbie.py +166 -0
  8. pyxllib/algo/pupil.py +629 -0
  9. pyxllib/algo/shapelylib.py +67 -0
  10. pyxllib/algo/specialist.py +241 -0
  11. pyxllib/algo/stat.py +494 -0
  12. pyxllib/algo/treelib.py +149 -0
  13. pyxllib/algo/unitlib.py +66 -0
  14. pyxllib/autogui/__init__.py +5 -0
  15. pyxllib/autogui/activewin.py +246 -0
  16. pyxllib/autogui/all.py +9 -0
  17. pyxllib/autogui/autogui.py +852 -0
  18. pyxllib/autogui/uiautolib.py +362 -0
  19. pyxllib/autogui/virtualkey.py +102 -0
  20. pyxllib/autogui/wechat.py +827 -0
  21. pyxllib/autogui/wechat_msg.py +421 -0
  22. pyxllib/autogui/wxautolib.py +84 -0
  23. pyxllib/cv/__init__.py +1 -11
  24. pyxllib/cv/expert.py +267 -0
  25. pyxllib/cv/{imlib.py → imfile.py} +18 -83
  26. pyxllib/cv/imhash.py +39 -0
  27. pyxllib/cv/pupil.py +9 -0
  28. pyxllib/cv/rgbfmt.py +1525 -0
  29. pyxllib/cv/slidercaptcha.py +137 -0
  30. pyxllib/cv/trackbartools.py +163 -49
  31. pyxllib/cv/xlcvlib.py +1040 -0
  32. pyxllib/cv/xlpillib.py +423 -0
  33. pyxllib/data/__init__.py +0 -0
  34. pyxllib/data/echarts.py +240 -0
  35. pyxllib/data/jsonlib.py +89 -0
  36. pyxllib/{util/oss2_.py → data/oss.py} +11 -9
  37. pyxllib/data/pglib.py +1127 -0
  38. pyxllib/data/sqlite.py +568 -0
  39. pyxllib/{util → data}/sqllib.py +13 -31
  40. pyxllib/ext/JLineViewer.py +505 -0
  41. pyxllib/ext/__init__.py +6 -0
  42. pyxllib/{util → ext}/demolib.py +119 -35
  43. pyxllib/ext/drissionlib.py +277 -0
  44. pyxllib/ext/kq5034lib.py +12 -0
  45. pyxllib/{util/main.py → ext/old.py} +122 -284
  46. pyxllib/ext/qt.py +449 -0
  47. pyxllib/ext/robustprocfile.py +497 -0
  48. pyxllib/ext/seleniumlib.py +76 -0
  49. pyxllib/{util/tklib.py → ext/tk.py} +10 -11
  50. pyxllib/ext/unixlib.py +827 -0
  51. pyxllib/ext/utools.py +351 -0
  52. pyxllib/{util/webhooklib.py → ext/webhook.py} +45 -17
  53. pyxllib/ext/win32lib.py +40 -0
  54. pyxllib/ext/wjxlib.py +88 -0
  55. pyxllib/ext/wpsapi.py +124 -0
  56. pyxllib/ext/xlwork.py +9 -0
  57. pyxllib/ext/yuquelib.py +1105 -0
  58. pyxllib/file/__init__.py +17 -0
  59. pyxllib/file/docxlib.py +761 -0
  60. pyxllib/{util → file}/gitlib.py +40 -27
  61. pyxllib/file/libreoffice.py +165 -0
  62. pyxllib/file/movielib.py +148 -0
  63. pyxllib/file/newbie.py +10 -0
  64. pyxllib/file/onenotelib.py +1469 -0
  65. pyxllib/file/packlib/__init__.py +330 -0
  66. pyxllib/{util → file/packlib}/zipfile.py +598 -195
  67. pyxllib/file/pdflib.py +426 -0
  68. pyxllib/file/pupil.py +185 -0
  69. pyxllib/file/specialist/__init__.py +685 -0
  70. pyxllib/{basic/_5_dirlib.py → file/specialist/dirlib.py} +364 -93
  71. pyxllib/file/specialist/download.py +193 -0
  72. pyxllib/file/specialist/filelib.py +2829 -0
  73. pyxllib/file/xlsxlib.py +3131 -0
  74. pyxllib/file/xlsyncfile.py +341 -0
  75. pyxllib/prog/__init__.py +5 -0
  76. pyxllib/prog/cachetools.py +64 -0
  77. pyxllib/prog/deprecatedlib.py +233 -0
  78. pyxllib/prog/filelock.py +42 -0
  79. pyxllib/prog/ipyexec.py +253 -0
  80. pyxllib/prog/multiprogs.py +940 -0
  81. pyxllib/prog/newbie.py +451 -0
  82. pyxllib/prog/pupil.py +1197 -0
  83. pyxllib/{sitepackages.py → prog/sitepackages.py} +5 -3
  84. pyxllib/prog/specialist/__init__.py +391 -0
  85. pyxllib/prog/specialist/bc.py +203 -0
  86. pyxllib/prog/specialist/browser.py +497 -0
  87. pyxllib/prog/specialist/common.py +347 -0
  88. pyxllib/prog/specialist/datetime.py +199 -0
  89. pyxllib/prog/specialist/tictoc.py +240 -0
  90. pyxllib/prog/specialist/xllog.py +180 -0
  91. pyxllib/prog/xlosenv.py +108 -0
  92. pyxllib/stdlib/__init__.py +17 -0
  93. pyxllib/{util → stdlib}/tablepyxl/__init__.py +1 -3
  94. pyxllib/{util → stdlib}/tablepyxl/style.py +1 -1
  95. pyxllib/{util → stdlib}/tablepyxl/tablepyxl.py +2 -4
  96. pyxllib/text/__init__.py +8 -0
  97. pyxllib/text/ahocorasick.py +39 -0
  98. pyxllib/text/airscript.js +744 -0
  99. pyxllib/text/charclasslib.py +121 -0
  100. pyxllib/text/jiebalib.py +267 -0
  101. pyxllib/text/jinjalib.py +32 -0
  102. pyxllib/text/jsa_ai_prompt.md +271 -0
  103. pyxllib/text/jscode.py +922 -0
  104. pyxllib/text/latex/__init__.py +158 -0
  105. pyxllib/text/levenshtein.py +303 -0
  106. pyxllib/text/nestenv.py +1215 -0
  107. pyxllib/text/newbie.py +300 -0
  108. pyxllib/text/pupil/__init__.py +8 -0
  109. pyxllib/text/pupil/common.py +1121 -0
  110. pyxllib/text/pupil/xlalign.py +326 -0
  111. pyxllib/text/pycode.py +47 -0
  112. pyxllib/text/specialist/__init__.py +8 -0
  113. pyxllib/text/specialist/common.py +112 -0
  114. pyxllib/text/specialist/ptag.py +186 -0
  115. pyxllib/text/spellchecker.py +172 -0
  116. pyxllib/text/templates/echart_base.html +11 -0
  117. pyxllib/text/templates/highlight_code.html +17 -0
  118. pyxllib/text/templates/latex_editor.html +103 -0
  119. pyxllib/text/vbacode.py +17 -0
  120. pyxllib/text/xmllib.py +747 -0
  121. pyxllib/xl.py +39 -0
  122. pyxllib/xlcv.py +17 -0
  123. pyxllib-0.3.197.dist-info/METADATA +48 -0
  124. pyxllib-0.3.197.dist-info/RECORD +126 -0
  125. {pyxllib-0.0.43.dist-info → pyxllib-0.3.197.dist-info}/WHEEL +4 -5
  126. pyxllib/basic/_1_strlib.py +0 -945
  127. pyxllib/basic/_2_timelib.py +0 -488
  128. pyxllib/basic/_3_pathlib.py +0 -916
  129. pyxllib/basic/_4_loglib.py +0 -419
  130. pyxllib/basic/__init__.py +0 -54
  131. pyxllib/basic/arrow_.py +0 -250
  132. pyxllib/basic/chardet_.py +0 -66
  133. pyxllib/basic/dirlib.py +0 -529
  134. pyxllib/basic/dprint.py +0 -202
  135. pyxllib/basic/extension.py +0 -12
  136. pyxllib/basic/judge.py +0 -31
  137. pyxllib/basic/log.py +0 -204
  138. pyxllib/basic/pathlib_.py +0 -705
  139. pyxllib/basic/pytictoc.py +0 -102
  140. pyxllib/basic/qiniu_.py +0 -61
  141. pyxllib/basic/strlib.py +0 -761
  142. pyxllib/basic/timer.py +0 -132
  143. pyxllib/cv/cv.py +0 -834
  144. pyxllib/cv/cvlib/_1_geo.py +0 -543
  145. pyxllib/cv/cvlib/_2_cvprcs.py +0 -309
  146. pyxllib/cv/cvlib/_2_imgproc.py +0 -594
  147. pyxllib/cv/cvlib/_3_pilprcs.py +0 -80
  148. pyxllib/cv/cvlib/_4_cvimg.py +0 -211
  149. pyxllib/cv/cvlib/__init__.py +0 -10
  150. pyxllib/cv/debugtools.py +0 -82
  151. pyxllib/cv/fitz_.py +0 -300
  152. pyxllib/cv/installer.py +0 -42
  153. pyxllib/debug/_0_installer.py +0 -38
  154. pyxllib/debug/_1_typelib.py +0 -277
  155. pyxllib/debug/_2_chrome.py +0 -198
  156. pyxllib/debug/_3_showdir.py +0 -161
  157. pyxllib/debug/_4_bcompare.py +0 -140
  158. pyxllib/debug/__init__.py +0 -49
  159. pyxllib/debug/bcompare.py +0 -132
  160. pyxllib/debug/chrome.py +0 -198
  161. pyxllib/debug/installer.py +0 -38
  162. pyxllib/debug/showdir.py +0 -158
  163. pyxllib/debug/typelib.py +0 -278
  164. pyxllib/image/__init__.py +0 -12
  165. pyxllib/torch/__init__.py +0 -20
  166. pyxllib/torch/modellib.py +0 -37
  167. pyxllib/torch/trainlib.py +0 -344
  168. pyxllib/util/__init__.py +0 -20
  169. pyxllib/util/aip_.py +0 -141
  170. pyxllib/util/casiadb.py +0 -59
  171. pyxllib/util/excellib.py +0 -495
  172. pyxllib/util/filelib.py +0 -612
  173. pyxllib/util/jsondata.py +0 -27
  174. pyxllib/util/jsondata2.py +0 -92
  175. pyxllib/util/labelmelib.py +0 -139
  176. pyxllib/util/onepy/__init__.py +0 -29
  177. pyxllib/util/onepy/onepy.py +0 -574
  178. pyxllib/util/onepy/onmanager.py +0 -170
  179. pyxllib/util/pyautogui_.py +0 -219
  180. pyxllib/util/textlib.py +0 -1305
  181. pyxllib/util/unorder.py +0 -22
  182. pyxllib/util/xmllib.py +0 -639
  183. pyxllib-0.0.43.dist-info/METADATA +0 -39
  184. pyxllib-0.0.43.dist-info/RECORD +0 -80
  185. pyxllib-0.0.43.dist-info/top_level.txt +0 -1
  186. {pyxllib-0.0.43.dist-info → pyxllib-0.3.197.dist-info/licenses}/LICENSE +0 -0
@@ -1,277 +0,0 @@
1
- #!/usr/bin/env python3
2
- # -*- coding: utf-8 -*-
3
- # @Author : 陈坤泽
4
- # @Email : 877362867@qq.com
5
- # @Data : 2020/06/02 11:09
6
-
7
-
8
- from collections import defaultdict, Counter
9
-
10
- import pandas as pd
11
-
12
- from pyxllib.basic import *
13
-
14
-
15
- def east_asian_len(s, ambiguous_width=None):
16
- import pandas.io.formats.format as fmt
17
- return fmt.EastAsianTextAdjustment().len(s)
18
-
19
-
20
- def east_asian_shorten(s, width=50, placeholder='...'):
21
- """考虑中文情况下的域宽截断
22
-
23
- :param s: 要处理的字符串
24
- :param width: 宽度上限,仅能达到width-1的宽度
25
- :param placeholder: 如果做了截断,末尾补足字符
26
-
27
- # width比placeholder还小
28
- >>> east_asian_shorten('a', 2)
29
- 'a'
30
- >>> east_asian_shorten('a啊b'*4, 3)
31
- '..'
32
- >>> east_asian_shorten('a啊b'*4, 4)
33
- '...'
34
-
35
- >>> east_asian_shorten('a啊b'*4, 5, '...')
36
- 'a...'
37
- >>> east_asian_shorten('a啊b'*4, 11)
38
- 'a啊ba啊...'
39
- >>> east_asian_shorten('a啊b'*4, 16, '...')
40
- 'a啊ba啊ba啊b...'
41
- >>> east_asian_shorten('a啊b'*4, 18, '...')
42
- 'a啊ba啊ba啊ba啊b'
43
- """
44
- # 一、如果字符串本身不到width设限,返回原值
45
- s = textwrap.shorten(s, width * 3, placeholder='') # 用textwrap的折行功能,尽量不删除文本
46
- n = east_asian_len(s)
47
- if n < width: return s
48
-
49
- # 二、如果输入的width比placeholder还短
50
- width -= 1
51
- m = east_asian_len(placeholder)
52
- if width <= m:
53
- return placeholder[:width]
54
-
55
- # 三、需要添加 placeholder
56
- # 1 计算长度
57
- width -= m
58
-
59
- # 2 截取s
60
- try:
61
- s = s.encode('gbk')[:width].decode('gbk', errors='ignore')
62
- except UnicodeEncodeError:
63
- i, count = 0, m
64
- while i < n and count <= width:
65
- if ord(s[i]) > 127:
66
- count += 2
67
- else:
68
- count += 1
69
- i += 1
70
- s = s[:i]
71
-
72
- return s + placeholder
73
-
74
-
75
- def dataframe_str(df, *args, ambiguous_as_wide=None, shorten=True):
76
- """输出DataFrame
77
- DataFrame可以直接输出的,这里是增加了对中文字符的对齐效果支持
78
-
79
- :param df: DataFrame数据结构
80
- :param args: option_context格式控制
81
- :param ambiguous_as_wide: 是否对①②③这种域宽有歧义的设为宽字符
82
- win32平台上和linux上①域宽不同,默认win32是域宽2,linux是域宽1
83
- :param shorten: 是否对每个元素提前进行字符串化并控制长度在display.max_colwidth以内
84
- 因为pandas的字符串截取遇到中文是有问题的,可以用我自定义的函数先做截取
85
- 默认开启,不过这步比较消耗时间
86
-
87
- >> df = pd.DataFrame({'哈哈': ['a'*100, '哈\n①'*10, 'a哈'*100]})
88
- 哈哈
89
- 0 aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa...
90
- 1 哈 ①哈 ①哈 ①哈 ①哈 ①哈 ①哈 ①哈 ①哈 ①...
91
- 2 a哈a哈a哈a哈a哈a哈a哈a哈a哈a哈a哈a哈a哈a哈a哈a...
92
- """
93
- import pandas as pd
94
-
95
- if ambiguous_as_wide is None:
96
- ambiguous_as_wide = sys.platform == 'win32'
97
- with pd.option_context('display.unicode.east_asian_width', True, # 中文输出必备选项,用来控制正确的域宽
98
- 'display.unicode.ambiguous_as_wide', ambiguous_as_wide,
99
- 'max_columns', 20, # 最大列数设置到20列
100
- 'display.width', 200, # 最大宽度设置到200
101
- *args):
102
- if shorten: # applymap可以对所有的元素进行映射处理,并返回一个新的df
103
- df = df.applymap(lambda x: east_asian_shorten(str(x), pd.options.display.max_colwidth))
104
- s = str(df)
105
- return s
106
-
107
-
108
- def prettifystr(s):
109
- """对一个对象用更友好的方式字符串化
110
-
111
- :param s: 输入类型不做限制,会将其以友好的形式格式化
112
- :return: 格式化后的字符串
113
- """
114
- title = ''
115
- if isinstance(s, str):
116
- pass
117
- elif isinstance(s, Counter): # Counter要按照出现频率显示
118
- li = s.most_common()
119
- title = f'collections.Counter长度:{len(s)}\n'
120
- # 不使用复杂的pd库,先简单用pprint即可
121
- # df = pd.DataFrame.from_records(s, columns=['value', 'count'])
122
- # s = dataframe_str(df)
123
- s = pprint.pformat(li)
124
- elif isinstance(s, (list, tuple)):
125
- title = f'{typename(s)}长度:{len(s)}\n'
126
- s = pprint.pformat(s)
127
- elif isinstance(s, (dict, set)):
128
- title = f'{typename(s)}长度:{len(s)}\n'
129
- s = pprint.pformat(s)
130
- else: # 其他的采用默认的pformat
131
- s = pprint.pformat(s)
132
- return title + s
133
-
134
-
135
- class PrettifyStrDecorator:
136
- """将函数的返回值字符串化(调用 prettifystr 美化)"""
137
-
138
- def __init__(self, func):
139
- self.func = func # 使用self.func可以索引回原始函数名称
140
- self.last_raw_res = None # last raw result,上一次执行函数的原始结果
141
-
142
- def __call__(self, *args, **kwargs):
143
- self.last_raw_res = self.func(*args, **kwargs)
144
- return prettifystr(self.last_raw_res)
145
-
146
-
147
- def dict2list(d: dict, *, nsort=False):
148
- """字典转n*2的list
149
- :param d: 字典
150
- :param nsort:
151
- True: 对key使用自然排序
152
- False: 使用d默认的遍历顺序
153
- :return:
154
- """
155
- ls = list(d.items())
156
- if nsort:
157
- ls = sorted(ls, key=lambda x: natural_sort_key(str(x[0])))
158
- return ls
159
-
160
-
161
- def dict2df(d):
162
- """dict类型转DataFrame类型"""
163
- name = typename(d)
164
- if isinstance(d, Counter):
165
- li = d.most_common()
166
- else:
167
- li = dict2list(d, nsort=True)
168
- return pd.DataFrame.from_records(li, columns=(f'{name}-key', f'{name}-value'))
169
-
170
-
171
- def list2df(li):
172
- if li and isinstance(li[0], (list, tuple)): # 有两维时按表格显示
173
- df = pd.DataFrame.from_records(li)
174
- else: # 只有一维时按一列显示
175
- df = pd.DataFrame(pd.Series(li), columns=(typename(li),))
176
- return df
177
-
178
-
179
- def try2df(arg):
180
- """尝试将各种不同的类型转成dataframe"""
181
- if isinstance(arg, dict):
182
- df = dict2df(arg)
183
- elif isinstance(arg, (list, tuple)):
184
- df = list2df(arg)
185
- elif isinstance(arg, pd.Series):
186
- df = pd.DataFrame(arg)
187
- else:
188
- df = arg
189
- return df
190
-
191
-
192
- class NestedDict:
193
- """ 字典嵌套结构相关功能
194
-
195
- TODO 感觉跟 pprint 的嵌套识别美化输出相关,可能有些代码是可以结合简化的~~
196
- """
197
-
198
- @classmethod
199
- def has_subdict(cls, data, include_self=True):
200
- """是否含有dict子结构
201
- :param include_self: 是否包含自身,即data本身是一个dict的话,也认为has_subdict是True
202
- """
203
- if include_self and isinstance(data, dict):
204
- return True
205
- elif isinstance(data, (list, tuple, set)):
206
- for v in data:
207
- if cls.has_subdict(v):
208
- return True
209
- return False
210
-
211
- @classmethod
212
- def to_html_table(cls, data, max_items=10):
213
- """ 以html表格套表格的形式,展示一个嵌套结构数据
214
- :param data: 数据
215
- :param max_items: 项目显示上限,有些数据项目太多了,要精简下
216
- 设为假值则不设上限
217
- :return:
218
- """
219
-
220
- def tohtml(d):
221
- if max_items:
222
- df = try2df(d)
223
- if len(df) > max_items:
224
- n = len(df)
225
- return df[:max_items].to_html(escape=False) + f'... {n - 1}'
226
- else:
227
- return df.to_html(escape=False)
228
- else:
229
- return try2df(d).to_html(escape=False)
230
-
231
- if not cls.has_subdict(data):
232
- res = str(data)
233
- elif isinstance(data, dict):
234
- if isinstance(data, Counter):
235
- d = data
236
- else:
237
- d = dict()
238
- for k, v in data.items():
239
- if cls.has_subdict(v):
240
- v = cls.to_html_table(v, max_items=max_items)
241
- d[k] = v
242
- res = tohtml(d)
243
- else:
244
- li = [cls.to_html_table(x, max_items=max_items) for x in data]
245
- res = tohtml(li)
246
-
247
- return res.replace('\n', ' ')
248
-
249
-
250
- class KeyValuesCounter:
251
- """ 各种键值对出现次数的统计
252
- 会递归找子字典结构,但不存储结构信息,只记录纯粹的键值对信息
253
-
254
- 应用场景:对未知的json结构,批量读取后,显示所有键值对的出现情况
255
- """
256
-
257
- def __init__(self):
258
- self.kvs = defaultdict(Counter)
259
-
260
- def add(self, data, max_value_length=100):
261
- """
262
- :param max_value_length: 添加的值,进行截断,防止有些值太长
263
- """
264
- if not NestedDict.has_subdict(data):
265
- return
266
- elif isinstance(data, dict):
267
- for k, v in data.items():
268
- if NestedDict.has_subdict(v):
269
- self.add(v)
270
- else:
271
- self.kvs[k][shorten(str(v), max_value_length)] += 1
272
- else: # 否则 data 应该是个可迭代对象,才可能含有dict
273
- for x in data:
274
- self.add(x)
275
-
276
- def to_html_table(self, max_items=10):
277
- return NestedDict.to_html_table(self.kvs, max_items=max_items)
@@ -1,198 +0,0 @@
1
- #!/usr/bin/env python3
2
- # -*- coding: utf-8 -*-
3
- # @Author : 陈坤泽
4
- # @Email : 877362867@qq.com
5
- # @Data : 2020/05/30 22:43
6
-
7
-
8
- import html
9
- import subprocess
10
- import pandas as pd
11
-
12
- from pyxllib.debug._1_typelib import *
13
-
14
-
15
- def getasizeof(*objs, **opts):
16
- """获得所有类的大小,底层用pympler.asizeof实现"""
17
- from pympler import asizeof
18
-
19
- try:
20
- res = asizeof.asizeof(*objs, **opts)
21
- # except TypeError: # sqlalchemy.exc.InvalidRequestError
22
- except:
23
- res = -1
24
- return res
25
-
26
-
27
- def viewfiles(procname, *files, **kwargs):
28
- """调用procname相关的文件程序打开files
29
- :param procname: 程序名
30
- :param files: 一个文件名参数清单,每一个都是文件路径,或者是字符串等可以用writefile转成文件的路径
31
- :param kwargs:
32
- save: 如果True,则会按时间保存文件名;否则采用特定名称,每次运行就会把上次的覆盖掉
33
- wait: 是否等待当前进程结束后,再运行后续py代码
34
- filename: 控制写入的文件名
35
- TODO:根据不同软件,这里还可以扩展很多功能
36
- :param kwargs:
37
- wait:
38
- True:在同一个进程中执行子程序,即会等待bc退出后,再进入下一步
39
- False:在新的进程中执行子程序
40
-
41
- 细节:注意bc跟其他程序有比较大不同,建议使用专用的bcompare函数
42
- 目前已知可以扩展多文件的有:chrome、notepad++、texstudio
43
-
44
- >> ls = list(range(100))
45
- >> viewfiles('notepad++', ls, save=True)
46
- """
47
- # 1 生成文件名
48
- ls = [] # 将最终所有绝对路径文件名存储到ls
49
- save = kwargs.get('save')
50
-
51
- basename = ext = None
52
- if 'filename' in kwargs and kwargs['filename']:
53
- basename, ext = os.path.splitext(kwargs['filename'])
54
-
55
- for i, t in enumerate(files):
56
- if Path(t).is_file() or is_url(t):
57
- ls.append(str(t))
58
- else:
59
- bn = basename or ''
60
- ls.append(Path(bn, ext, Path.TEMP).write(t, if_exists=kwargs.get('if_exists', 'error')).fullpath)
61
-
62
- # 2 调用程序(并计算外部操作时间)
63
- tictoc = TicToc()
64
- try:
65
- if kwargs.get('wait'):
66
- subprocess.run([procname, *ls])
67
- else:
68
- subprocess.Popen([procname, *ls])
69
- except FileNotFoundError:
70
- if procname in ('chrome', 'chrome.exe'):
71
- procname = 'explorer' # 如果是谷歌浏览器找不到,尝试用系统默认浏览器
72
- viewfiles(procname, *files, **kwargs)
73
- else:
74
- raise FileNotFoundError(f'未找到程序:{procname}。请检查是否有安装及设置了环境变量。')
75
- return tictoc.tocvalue()
76
-
77
-
78
- def chrome(arg_, **kwargs):
79
- r"""使用谷歌浏览器查看变量、文件等内容,详细用法见底层函数 viewfiles
80
-
81
- :param arg_: 支持输入多种类型
82
- 文件、url,会用浏览器直接打开
83
- dict,会先转df
84
- :param kwargs: 如果数据可以转为df,在使用to_html接口的时候可以设置相关格式参数,常用的有
85
- escape=True,是否解析html内容,默认True不解析
86
-
87
- >> chrome(r'C:\Users\kzche\Desktop\b.xml') # 使用chrome查看文件内容
88
- >> chrome('aabb') # 使用chrome查看一个字符串值
89
- >> chrome([123, 456]) # 使用chrome查看一个变量值
90
-
91
- 这个函数可以浏览文本、list、dict、DataFrame表格数据、图片、html等各种文件的超级工具
92
- """
93
- # 1 如果是文件、url,则直接打开
94
- if is_file(arg_) or is_url(arg_):
95
- viewfiles('chrome.exe', arg_)
96
- return
97
-
98
- # 2 如果是其他类型,则先转成文件,再打开
99
- arg = try2df(arg_)
100
- if isinstance(arg, pd.DataFrame): # DataFrame在网页上有更合适的显示效果
101
- t = f'==== 类继承关系:{inspect.getmro(type(arg_))},' \
102
- + f'内存消耗:{sys.getsizeof(arg_)}(递归子类总大小:{getasizeof(arg_)})Byte ===='
103
- t = '<p>' + html.escape(t) + '</p>'
104
- content = arg.to_html(**kwargs)
105
- filename = Path('', '.html', Path.TEMP).write(t + content, etag=True, if_exists='ignore')
106
- viewfiles('chrome.exe', str(filename))
107
- elif getattr(arg, 'render', None): # pyecharts 等表格对象,可以用render生成html表格显示
108
- try:
109
- name = arg.options['title'][0]['text']
110
- except (LookupError, TypeError):
111
- name = Datetime().strftime('%H%M%S_%f')
112
- filename = Path(name, '.html', Path.TEMP).fullpath
113
- arg.render(path=filename)
114
- viewfiles('chrome.exe', filename)
115
- else:
116
- name = Datetime().strftime('%H%M%S_%f')
117
- filename = Path(name, '.txt', Path.TEMP).write(arg).fullpath
118
- viewfiles('chrome.exe', filename)
119
-
120
-
121
- def view_jsons_kv(fd, files='**/*.json', encoding=None, max_items=10, max_value_length=100):
122
- """ demo_keyvaluescounter,查看目录下json数据的键值对信息
123
- :param fd: 目录
124
- :param files: 匹配的文件格式
125
- :param encoding: 文件编码
126
- :param max_items: 项目显示上限,有些数据项目太多了,要精简下
127
- 设为假值则不设上限
128
- :param max_value_length: 添加的值,进行截断,防止有些值太长
129
- :return:
130
- """
131
- kvc = KeyValuesCounter()
132
- d = Dir(fd)
133
- for p in d.select(files).filepaths:
134
- # print(p)
135
- data = p.read(encoding=encoding, mode='.json')
136
- kvc.add(data, max_value_length=max_value_length)
137
- p = Path(r'demo_keyvaluescounter.html', root=Path.TEMP)
138
- p.write(kvc.to_html_table(max_items=max_items), if_exists='replace')
139
- chrome(p.fullpath)
140
-
141
-
142
- def check_repeat_filenames(dir, key='stem', link=True):
143
- """ 检查目录下文件结构情况的功能函数
144
-
145
- https://www.yuque.com/xlpr/pyxllib/check_repeat_filenames
146
-
147
- :param dir: 目录Dir类型,也可以输入路径,如果没有files成员,则默认会获取所有子文件
148
- :param key: 以什么作为行分组的key名称,基本上都是用'stem',偶尔可能用'name'
149
- 遇到要忽略 -eps-to-pdf.pdf 这种后缀的,也可以自定义处理规则
150
- 例如 key=lambda p: re.sub(r'-eps-to-pdf', '', p.stem).lower()
151
- :param link: 默认True会生成文件超链接
152
- :return: 一个df表格,行按照key的规则分组,列默认按suffix扩展名分组
153
- """
154
- # 1 智能解析dir参数
155
- if not isinstance(dir, Dir):
156
- dir = Dir(dir)
157
- if not dir.files:
158
- dir = dir.select('**/*', type_='file')
159
-
160
- # 2 辅助函数,智能解析key参数
161
- if isinstance(key, str):
162
- def extract_key(p):
163
- return getattr(p, key).lower()
164
- elif callable(key):
165
- extract_key = key
166
- else:
167
- raise TypeError
168
-
169
- # 3 制作df表格数据
170
- columns = ['key', 'suffix', 'filename']
171
- li = []
172
- for f in dir.files:
173
- p = Path(f)
174
- li.append([extract_key(p), p.suffix.lower(), f])
175
- df = pd.DataFrame.from_records(li, columns=columns)
176
-
177
- # 4 分组
178
- def joinfile(files):
179
- if len(files):
180
- if link:
181
- return ', '.join([f'<a href="{dir / f}" target="_blank">{f}</a>' for f in files])
182
- else:
183
- return ', '.join(files)
184
- else:
185
- return ''
186
-
187
- groups = df.groupby(['key', 'suffix']).agg({'filename': joinfile})
188
- groups.reset_index(inplace=True)
189
- view_table = groups.pivot(index='key', columns='suffix', values='filename')
190
- view_table.fillna('', inplace=True)
191
-
192
- # 5 判断每个key的文件总数
193
- count_df = df.groupby('key').agg({'filename': 'count'})
194
- view_table = pd.concat([view_table, count_df], axis=1)
195
- view_table.rename({'filename': 'count'}, axis=1, inplace=True)
196
-
197
- chrome(view_table, escape=not link)
198
- return df
@@ -1,161 +0,0 @@
1
- #!/usr/bin/env python3
2
- # -*- coding: utf-8 -*-
3
- # @Author : 陈坤泽
4
- # @Email : 877362867@qq.com
5
- # @Data : 2020/06/01
6
-
7
-
8
- import enum
9
- import html
10
- import subprocess
11
-
12
- import pandas as pd
13
- from bs4 import BeautifulSoup
14
-
15
- from pyxllib.basic import *
16
- from pyxllib.debug._1_typelib import dataframe_str
17
- from pyxllib.debug._2_chrome import getasizeof
18
-
19
-
20
- def getmembers(object, predicate=None):
21
- """自己重写改动的 inspect.getmembers
22
-
23
- TODO 这个实现好复杂,对于成员,直接用dir不就好了?
24
- """
25
- from inspect import isclass, getmro
26
- import types
27
-
28
- if isclass(object):
29
- mro = (object,) + getmro(object)
30
- else:
31
- mro = ()
32
- results = []
33
- processed = set()
34
- names = dir(object)
35
- # :dd any DynamicClassAttributes to the list of names if object is a class;
36
- # this may result in duplicate entries if, for example, a virtual
37
- # attribute with the same name as a DynamicClassAttribute exists
38
- try:
39
- for base in object.__bases__:
40
- for k, v in base.__dict__.items():
41
- if isinstance(v, types.DynamicClassAttribute):
42
- names.append(k)
43
- except AttributeError:
44
- pass
45
- for key in names:
46
- # First try to get the value via getattr. Some descriptors don't
47
- # like calling their __get__ (see bug #1785), so fall back to
48
- # looking in the __dict__.
49
- try:
50
- value = getattr(object, key)
51
- # handle the duplicate key
52
- if key in processed:
53
- raise AttributeError
54
- # except AttributeError:
55
- except: # 加了这种异常获取,190919周四15:14,sqlalchemy.exc.InvalidRequestError
56
- dprint(key) # 抓不到对应的这个属性
57
- for base in mro:
58
- if key in base.__dict__:
59
- value = base.__dict__[key]
60
- break
61
- else:
62
- # could be a (currently) missing slot member, or a buggy
63
- # __dir__; discard and move on
64
- continue
65
-
66
- if not predicate or predicate(value):
67
- results.append((key, value))
68
- processed.add(key)
69
- results.sort(key=lambda pair: pair[0])
70
- return results
71
-
72
-
73
- def showdir(c, *, to_html=None, printf=True):
74
- """查看类信息
75
- 会罗列出类c的所有成员方法、成员变量,并生成一个html文
76
-
77
- 查阅一个对象的成员变量及成员方法
78
- 为了兼容linux输出df时也能对齐,有几个中文域宽处理相关的函数
79
-
80
- :param c: 要处理的对象
81
- :param to_html:
82
- win32上默认True,用chrome、explorer打开
83
- linux上默认False,直接输出到控制台
84
- :param printf:
85
- 默认是True,会输出到浏览器或控制条
86
- 设为False则不输出
87
- """
88
- # 1 输出类表头
89
- res = []
90
- object_name = func_input_message(2)['argnames'][0]
91
- if to_html is None:
92
- to_html = sys.platform == 'win32'
93
- newline = '<br/>' if to_html else '\n'
94
-
95
- t = f'==== 对象名称:{object_name},类继承关系:{inspect.getmro(type(c))},' \
96
- + f'内存消耗:{sys.getsizeof(c)}(递归子类总大小:{getasizeof(c)})Byte ===='
97
-
98
- if to_html:
99
- res.append('<p>')
100
- t = html.escape(t) + '</p>'
101
- res.append(t + newline)
102
-
103
- # 2 html的样式精调
104
- def df2str(df):
105
- if to_html:
106
- df = df.applymap(str) # 不转成文本经常有些特殊函数会报错
107
- df.index += 1 # 编号从1开始
108
- # pd.options.display.max_colwidth = -1 # 如果临时需要显示完整内容
109
- t = df.to_html()
110
- table = BeautifulSoup(t, 'lxml')
111
- table.thead.tr['bgcolor'] = 'LightSkyBlue' # 设置表头颜色
112
- ch = 'A' if '成员变量' in table.tr.contents[3].string else 'F'
113
- table.thead.tr.th.string = f'编号{ch}{len(df)}'
114
- t = table.prettify()
115
- else:
116
- # 直接转文本,遇到中文是会对不齐的,但是showdir主要用途本来就是在浏览器看的,这里就不做调整了
117
- t = dataframe_str(df)
118
- return t
119
-
120
- # 3 添加成员变量和成员函数
121
- # 成员变量
122
- members = getmembers(c)
123
- methods = filter(lambda m: not callable(getattr(c, m[0])), members)
124
- ls = []
125
- for ele in methods:
126
- k, v = ele
127
- if k.endswith(r'________'): # 这个名称的变量是我代码里的特殊标记,不显示
128
- continue
129
- attr = getattr(c, k)
130
- if isinstance(attr, enum.IntFlag): # 对re.RegexFlag等枚举类输出整数值
131
- v = typename(attr) + ',' + str(int(attr)) + ',' + str(v)
132
- else:
133
- try:
134
- text = str(v)
135
- except:
136
- text = '取不到str值'
137
- v = typename(attr) + ',' + text
138
- ls.append([k, v])
139
- df = pd.DataFrame.from_records(ls, columns=['成员变量', '描述'])
140
- res.append(df2str(df) + newline)
141
-
142
- # 成员函数
143
- methods = filter(lambda m: callable(getattr(c, m[0])), members)
144
- df = pd.DataFrame.from_records(methods, columns=['成员函数', '描述'])
145
- res.append(df2str(df) + newline)
146
- res = newline.join(res)
147
-
148
- # 4 使用chrome.exe浏览或输出到控制台
149
- # 这里底层可以封装一个chrome函数来调用,但是这个chrome需要依赖太多功能,故这里暂时手动简单调用
150
- if to_html:
151
- filename = Path(object_name, suffix='.html', root=Path.TEMP). \
152
- write(ensure_gbk(res), if_exists='replace').fullpath
153
- try:
154
- subprocess.run(['chrome.exe', filename])
155
- except FileNotFoundError:
156
- subprocess.run(['explorer', filename], shell=True)
157
- logging.warning('启动chrome.exe失败,可能是没有安装谷歌浏览器或配置环境变量。')
158
- else: # linux环境直接输出表格
159
- print(res)
160
-
161
- return res