pyxllib 0.3.108__tar.gz → 0.3.110__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.
- {pyxllib-0.3.108/pyxllib.egg-info → pyxllib-0.3.110}/PKG-INFO +1 -1
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/algo/pupil.py +100 -22
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/data/pglib.py +68 -35
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/data/sqlite.py +117 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/ext/kq5034lib.py +1 -1
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/file/libreoffice.py +1 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/file/specialist/filelib.py +44 -13
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/prog/newbie.py +3 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/prog/specialist/bc.py +5 -2
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/prog/specialist/browser.py +8 -2
- {pyxllib-0.3.108 → pyxllib-0.3.110/pyxllib.egg-info}/PKG-INFO +1 -1
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib.egg-info/SOURCES.txt +1 -0
- pyxllib-0.3.110/pyxlpr/data/tiktokenlib.py +43 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/setup.py +1 -1
- {pyxllib-0.3.108 → pyxllib-0.3.110}/LICENSE +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/MANIFEST.in +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/README.md +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/__init__.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/algo/__init__.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/algo/disjoint.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/algo/geo.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/algo/intervals.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/algo/matcher.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/algo/newbie.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/algo/shapelylib.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/algo/specialist.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/algo/stat.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/algo/treelib.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/algo/unitlib.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/cv/__init__.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/cv/expert.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/cv/imfile.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/cv/imhash.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/cv/pupil.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/cv/rgbfmt.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/cv/trackbartools.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/cv/xlcvlib.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/cv/xlpillib.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/data/__init__.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/data/echarts.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/data/jsonlib.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/data/oss.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/data/sqllib.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/ext/JLineViewer.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/ext/__init__.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/ext/autogui/__init__.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/ext/autogui/autogui.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/ext/autogui/virtualkey.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/ext/demolib.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/ext/drissionlib.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/ext/old.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/ext/qt.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/ext/robustprocfile.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/ext/seleniumlib.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/ext/tk.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/ext/unixlib.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/ext/utools.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/ext/webhook.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/ext/win32lib.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/ext/yuquelib.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/file/__init__.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/file/docxlib.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/file/gitlib.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/file/movielib.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/file/newbie.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/file/onenotelib.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/file/packlib/__init__.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/file/packlib/zipfile.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/file/pdflib.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/file/pupil.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/file/specialist/__init__.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/file/specialist/dirlib.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/file/specialist/download.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/file/xlsxlib.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/prog/__init__.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/prog/deprecatedlib.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/prog/ipyexec.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/prog/multiprocs.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/prog/pupil.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/prog/sitepackages.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/prog/specialist/__init__.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/prog/specialist/common.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/prog/specialist/datetime.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/prog/specialist/tictoc.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/prog/specialist/xllog.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/prog/xlosenv.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/stdlib/__init__.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/stdlib/tablepyxl/__init__.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/stdlib/tablepyxl/style.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/stdlib/tablepyxl/tablepyxl.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/text/__init__.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/text/ahocorasick.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/text/charclasslib.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/text/jiebalib.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/text/jscode.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/text/latex/__init__.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/text/levenshtein.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/text/nestenv.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/text/newbie.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/text/pupil/__init__.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/text/pupil/common.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/text/pupil/xlalign.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/text/pycode.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/text/specialist/__init__.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/text/specialist/common.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/text/specialist/ptag.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/text/spellchecker.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/text/vbacode.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/text/xmllib.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/xl.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib/xlcv.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib.egg-info/dependency_links.txt +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib.egg-info/requires.txt +2 -2
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxllib.egg-info/top_level.txt +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/__init__.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ai/__init__.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ai/clientlib.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ai/specialist.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ai/torch_app.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ai/xlpaddle.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ai/xltorch.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/data/__init__.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/data/coco.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/data/datacls.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/data/datasets.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/data/gptlib.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/data/icdar/__init__.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/data/icdar/deteval.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/data/icdar/icdar2013.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/data/icdar/iou.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/data/icdar/rrc_evaluation_funcs_1_1.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/data/imtextline.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/data/labelme.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/data/removeline.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/data/specialist.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/eval/__init__.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/paddleocr.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/__init__.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/configs/rec/multi_language/generate_multi_language_configs.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/data/__init__.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/data/imaug/ColorJitter.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/data/imaug/__init__.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/data/imaug/copy_paste.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/data/imaug/east_process.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/data/imaug/gen_table_mask.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/data/imaug/iaa_augment.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/data/imaug/label_ops.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/data/imaug/make_border_map.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/data/imaug/make_pse_gt.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/data/imaug/make_shrink_map.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/data/imaug/operators.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/data/imaug/pg_process.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/data/imaug/randaugment.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/data/imaug/random_crop_data.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/data/imaug/rec_img_aug.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/data/imaug/sast_process.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/data/imaug/text_image_aug/__init__.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/data/imaug/text_image_aug/augment.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/data/imaug/text_image_aug/warp_mls.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/data/lmdb_dataset.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/data/pgnet_dataset.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/data/pubtab_dataset.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/data/simple_dataset.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/losses/__init__.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/losses/ace_loss.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/losses/basic_loss.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/losses/center_loss.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/losses/cls_loss.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/losses/combined_loss.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/losses/det_basic_loss.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/losses/det_db_loss.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/losses/det_east_loss.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/losses/det_pse_loss.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/losses/det_sast_loss.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/losses/distillation_loss.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/losses/e2e_pg_loss.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/losses/kie_sdmgr_loss.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/losses/rec_aster_loss.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/losses/rec_att_loss.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/losses/rec_ctc_loss.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/losses/rec_enhanced_ctc_loss.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/losses/rec_nrtr_loss.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/losses/rec_sar_loss.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/losses/rec_srn_loss.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/losses/table_att_loss.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/metrics/__init__.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/metrics/cls_metric.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/metrics/det_metric.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/metrics/distillation_metric.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/metrics/e2e_metric.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/metrics/eval_det_iou.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/metrics/kie_metric.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/metrics/rec_metric.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/metrics/table_metric.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/architectures/__init__.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/architectures/base_model.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/architectures/distillation_model.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/backbones/__init__.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/backbones/det_mobilenet_v3.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/backbones/det_resnet_vd.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/backbones/det_resnet_vd_sast.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/backbones/e2e_resnet_vd_pg.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/backbones/kie_unet_sdmgr.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/backbones/rec_mobilenet_v3.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/backbones/rec_mv1_enhance.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/backbones/rec_nrtr_mtb.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/backbones/rec_resnet_31.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/backbones/rec_resnet_aster.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/backbones/rec_resnet_fpn.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/backbones/rec_resnet_vd.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/heads/__init__.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/heads/cls_head.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/heads/det_db_head.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/heads/det_east_head.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/heads/det_pse_head.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/heads/det_sast_head.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/heads/e2e_pg_head.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/heads/kie_sdmgr_head.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/heads/multiheadAttention.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/heads/rec_aster_head.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/heads/rec_att_head.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/heads/rec_ctc_head.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/heads/rec_nrtr_head.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/heads/rec_sar_head.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/heads/rec_srn_head.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/heads/self_attention.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/heads/table_att_head.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/necks/__init__.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/necks/db_fpn.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/necks/east_fpn.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/necks/fpn.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/necks/pg_fpn.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/necks/rnn.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/necks/sast_fpn.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/necks/table_fpn.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/transforms/__init__.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/transforms/stn.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/transforms/tps.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/modeling/transforms/tps_spatial_transformer.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/optimizer/__init__.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/optimizer/learning_rate.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/optimizer/lr_scheduler.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/optimizer/optimizer.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/optimizer/regularizer.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/postprocess/__init__.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/postprocess/cls_postprocess.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/postprocess/db_postprocess.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/postprocess/east_postprocess.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/postprocess/locality_aware_nms.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/postprocess/pg_postprocess.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/postprocess/pse_postprocess/__init__.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/postprocess/pse_postprocess/pse/__init__.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/postprocess/pse_postprocess/pse/setup.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/postprocess/pse_postprocess/pse_postprocess.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/postprocess/rec_postprocess.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/postprocess/sast_postprocess.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/tools/__init__.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/tools/eval.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/tools/export_center.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/tools/export_model.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/tools/infer/predict_cls.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/tools/infer/predict_det.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/tools/infer/predict_e2e.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/tools/infer/predict_rec.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/tools/infer/predict_system.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/tools/infer/utility.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/tools/infer_cls.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/tools/infer_det.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/tools/infer_e2e.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/tools/infer_kie.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/tools/infer_rec.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/tools/infer_table.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/tools/program.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/tools/test_hubserving.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/tools/train.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/tools/xlprog.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/EN_symbol_dict.txt +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/__init__.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/dict/ar_dict.txt +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/dict/arabic_dict.txt +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/dict/be_dict.txt +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/dict/bg_dict.txt +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/dict/chinese_cht_dict.txt +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/dict/cyrillic_dict.txt +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/dict/devanagari_dict.txt +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/dict/en_dict.txt +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/dict/fa_dict.txt +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/dict/french_dict.txt +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/dict/german_dict.txt +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/dict/hi_dict.txt +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/dict/it_dict.txt +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/dict/japan_dict.txt +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/dict/ka_dict.txt +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/dict/korean_dict.txt +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/dict/latin_dict.txt +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/dict/mr_dict.txt +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/dict/ne_dict.txt +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/dict/oc_dict.txt +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/dict/pu_dict.txt +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/dict/rs_dict.txt +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/dict/rsc_dict.txt +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/dict/ru_dict.txt +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/dict/ta_dict.txt +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/dict/table_dict.txt +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/dict/table_structure_dict.txt +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/dict/te_dict.txt +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/dict/ug_dict.txt +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/dict/uk_dict.txt +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/dict/ur_dict.txt +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/dict/xi_dict.txt +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/dict90.txt +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/e2e_metric/Deteval.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/e2e_metric/polygon_fast.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/e2e_utils/extract_batchsize.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/e2e_utils/extract_textpoint_fast.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/e2e_utils/extract_textpoint_slow.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/e2e_utils/pgnet_pp_utils.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/e2e_utils/visual.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/en_dict.txt +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/gen_label.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/ic15_dict.txt +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/iou.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/logging.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/network.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/ppocr_keys_v1.txt +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/profiler.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/save_load.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/stats.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppocr/utils/utility.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppstructure/__init__.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppstructure/predict_system.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppstructure/table/__init__.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppstructure/table/eval_table.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppstructure/table/matcher.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppstructure/table/predict_structure.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppstructure/table/predict_table.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppstructure/table/table_metric/__init__.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppstructure/table/table_metric/parallel.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppstructure/table/table_metric/table_metric.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppstructure/table/tablepyxl/__init__.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppstructure/table/tablepyxl/style.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppstructure/table/tablepyxl/tablepyxl.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/ppstructure/utility.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/pyxlpr/xlai.py +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/requirements.txt +0 -0
- {pyxllib-0.3.108 → pyxllib-0.3.110}/setup.cfg +0 -0
@@ -4,11 +4,14 @@
|
|
4
4
|
# @Email : 877362867@qq.com
|
5
5
|
# @Date : 2021/06/03 14:22
|
6
6
|
|
7
|
-
import
|
7
|
+
from bisect import bisect_right
|
8
8
|
from collections import defaultdict, Counter
|
9
|
+
import datetime
|
9
10
|
import math
|
10
11
|
import re
|
12
|
+
from statistics import quantiles
|
11
13
|
import sys
|
14
|
+
import textwrap
|
12
15
|
|
13
16
|
from pyxllib.prog.newbie import typename, human_readable_number
|
14
17
|
from pyxllib.text.pupil import listalign, int2myalphaenum
|
@@ -156,13 +159,17 @@ class ValuesStat2:
|
|
156
159
|
""" 240509周四17:33,第2代统计器
|
157
160
|
"""
|
158
161
|
|
159
|
-
def __init__(self, values=None, raw_values=None):
|
162
|
+
def __init__(self, values=None, raw_values=None, data_type=None):
|
160
163
|
from statistics import pstdev, mean
|
161
164
|
|
162
165
|
# 支持输入可能带有非数值类型的raw_values
|
163
166
|
if raw_values:
|
164
|
-
|
167
|
+
if 'timestamp' in data_type:
|
168
|
+
values = [x.timestamp() for x in raw_values if hasattr(x, 'timestamp')]
|
169
|
+
else:
|
170
|
+
values = [x for x in raw_values if isinstance(x, (int, float))] # todo 可能需要更泛用的判断数值的方法
|
165
171
|
|
172
|
+
self.date_type = data_type
|
166
173
|
self.raw_values = raw_values
|
167
174
|
values = values or []
|
168
175
|
self.values = sorted(values)
|
@@ -171,57 +178,128 @@ class ValuesStat2:
|
|
171
178
|
else:
|
172
179
|
self.raw_n = 0
|
173
180
|
self.n = len(values)
|
174
|
-
|
181
|
+
|
182
|
+
if 'timestamp' in data_type:
|
183
|
+
self.sum = None
|
184
|
+
else:
|
185
|
+
self.sum = sum(values)
|
186
|
+
|
175
187
|
if self.n:
|
176
188
|
self.mean = mean(self.values)
|
177
189
|
self.std = pstdev(self.values)
|
178
190
|
self.min, self.max = self.values[0], self.values[-1]
|
179
191
|
else:
|
180
|
-
self.mean = self.std = self.min = self.max =
|
192
|
+
self.mean = self.std = self.min = self.max = None
|
181
193
|
|
182
|
-
self.dist =
|
194
|
+
self.dist = None
|
183
195
|
|
184
196
|
def __len__(self):
|
185
197
|
return self.n
|
186
198
|
|
187
|
-
def
|
199
|
+
def _summary(self, unit=None, precision=4, percentile_count=5):
|
200
|
+
""" 返回字典结构的总结 """
|
188
201
|
""" 文本汇总性的报告
|
189
202
|
|
190
|
-
:param
|
203
|
+
:param percentile_count: 包括两个极值端点的切分点数,
|
191
204
|
设置2,就是不设置分位数,就是只展示最小、最大值
|
192
205
|
如果设置了3,就表示"中位数、二分位数",在展示的时候,会显示50%位置的分位数值
|
193
206
|
如果设置了5,就相当于"四分位数",会显示25%、50%、75%位置的分位数值
|
194
207
|
:param unit: 展示数值时使用的单位
|
195
208
|
:param precision: 展示数值时的精度
|
196
209
|
"""
|
197
|
-
from statistics import quantiles
|
198
210
|
|
211
|
+
# 1 各种细分的格式化方法
|
199
212
|
def fmt0(v):
|
213
|
+
# 数量类整数的格式
|
200
214
|
return human_readable_number(v, '万')
|
201
215
|
|
202
|
-
def
|
203
|
-
|
216
|
+
def fmt1(v):
|
217
|
+
if isinstance(v, str):
|
218
|
+
return v
|
219
|
+
return human_readable_number(v, unit or 'K', precision)
|
204
220
|
|
205
|
-
|
221
|
+
def fmt2(v):
|
222
|
+
# 日期类数据的格式化
|
223
|
+
# todo 这个应该数据的具体格式来设置的,但是这个现在有点难写,先写死
|
224
|
+
if isinstance(v, str):
|
225
|
+
return v
|
226
|
+
elif isinstance(v, (int, float)):
|
227
|
+
v = datetime.datetime.fromtimestamp(v)
|
228
|
+
|
229
|
+
return v.strftime(unit or '%Y-%m-%d %H:%M:%S')
|
230
|
+
|
231
|
+
def fmt2b(v):
|
232
|
+
# 时间长度类数据的格式化
|
233
|
+
return human_readable_number(v, '秒')
|
234
|
+
|
235
|
+
if 'timestamp' in self.date_type:
|
236
|
+
fmt = fmt2
|
237
|
+
fmtb = fmt2b
|
238
|
+
else:
|
239
|
+
fmt = fmtb = fmt1
|
240
|
+
|
241
|
+
# 2 生成统计报告
|
242
|
+
desc = {}
|
206
243
|
if self.raw_n and self.raw_n > self.n:
|
207
|
-
desc
|
244
|
+
desc["总数"] = f"{fmt0(self.n)}/{fmt0(self.raw_n)}≈{self.n / self.raw_n:.2%}"
|
245
|
+
else:
|
246
|
+
desc["总数"] = f"{fmt0(self.n)}"
|
208
247
|
|
209
|
-
|
210
|
-
|
211
|
-
|
248
|
+
if self.sum is not None:
|
249
|
+
desc["总和"] = f"{fmt(self.sum)}"
|
250
|
+
if self.mean is not None and self.std is not None:
|
251
|
+
desc["均值±标准差"] = f"{fmt(self.mean)}±{fmtb(self.std)}"
|
252
|
+
elif self.mean is not None:
|
253
|
+
desc["均值"] = f"{fmt(self.mean)}"
|
254
|
+
elif self.std is not None:
|
255
|
+
desc["标准差"] = f"{fmtb(self.std)}"
|
212
256
|
|
213
257
|
if self.values:
|
214
258
|
dist = [self.values[0]]
|
215
|
-
if
|
216
|
-
quartiles = quantiles(self.values, n=
|
259
|
+
if percentile_count > 2:
|
260
|
+
quartiles = quantiles(self.values, n=percentile_count - 1)
|
217
261
|
dist += quartiles
|
218
262
|
dist.append(self.values[-1])
|
219
263
|
|
220
|
-
desc
|
221
|
-
elif self.dist:
|
222
|
-
desc
|
264
|
+
desc["分布"] = '/'.join([fmt(v) for v in dist])
|
265
|
+
elif self.dist:
|
266
|
+
desc["分布"] = '/'.join([fmt(v) for v in self.dist])
|
267
|
+
|
268
|
+
return desc
|
269
|
+
|
270
|
+
def summary(self, unit=None, precision=4, percentile_count=5):
|
271
|
+
""" 文本汇总性的报告
|
272
|
+
|
273
|
+
:param percentile_count: 包括两个极值端点的切分点数,
|
274
|
+
设置2,就是不设置分位数,就是只展示最小、最大值
|
275
|
+
如果设置了3,就表示"中位数、二分位数",在展示的时候,会显示50%位置的分位数值
|
276
|
+
如果设置了5,就相当于"四分位数",会显示25%、50%、75%位置的分位数值
|
277
|
+
:param unit: 展示数值时使用的单位
|
278
|
+
:param precision: 展示数值时的精度
|
279
|
+
"""
|
280
|
+
desc = self._summary(unit, precision, percentile_count)
|
281
|
+
return '\t'.join([f"{key}: {value}" for key, value in desc.items()])
|
282
|
+
|
283
|
+
def calculate_ratios(self, x_values, fmt=False):
|
284
|
+
""" 计算并返回一个字典,其中包含每个 x_values 中的值与其小于等于该值的元素的比例
|
285
|
+
|
286
|
+
:param x_values: 一个数值列表,用来计算每个数值小于等于它的元素的比例
|
287
|
+
:param fmt: 直接将值格式化好
|
288
|
+
:return: 一个字典,键为输入的数值,值为对应的比例(百分比)
|
289
|
+
"""
|
290
|
+
ratio_dict = {}
|
291
|
+
for x in x_values:
|
292
|
+
position = bisect_right(self.values, x)
|
293
|
+
if self.n > 0:
|
294
|
+
ratio = (position / self.n)
|
295
|
+
else:
|
296
|
+
ratio = 0
|
297
|
+
ratio_dict[x] = ratio
|
298
|
+
|
299
|
+
if fmt:
|
300
|
+
ratio_dict = {x: f'{ratio:.2%}' for x, ratio in ratio_dict.items()}
|
223
301
|
|
224
|
-
return
|
302
|
+
return ratio_dict
|
225
303
|
|
226
304
|
|
227
305
|
class Groups:
|
@@ -46,7 +46,7 @@ from pyxllib.prog.pupil import utc_now, utc_timestamp
|
|
46
46
|
from pyxllib.prog.specialist import XlOsEnv
|
47
47
|
from pyxllib.algo.pupil import ValuesStat2
|
48
48
|
from pyxllib.file.specialist import get_etag
|
49
|
-
from pyxllib.data.sqlite import SqlBase
|
49
|
+
from pyxllib.data.sqlite import SqlBase, SqlBuilder
|
50
50
|
|
51
51
|
|
52
52
|
class Connection(psycopg.Connection, SqlBase):
|
@@ -147,6 +147,28 @@ WHERE {table_name}.{item_id_name} = cte.{item_id_name}"""
|
|
147
147
|
# cur.close()
|
148
148
|
return data
|
149
149
|
|
150
|
+
def exec2dict_batch(self, sql, batch_size=1000, **kwargs):
|
151
|
+
""" 分批返回数据的版本
|
152
|
+
|
153
|
+
:return:
|
154
|
+
第1个值,是一个迭代器,看起来仍然能一条一条返回,实际后台是按照batch_size打包获取的
|
155
|
+
第2个值,是数据总数
|
156
|
+
"""
|
157
|
+
if not isinstance(sql, SqlBuilder):
|
158
|
+
raise ValueError('暂时只能搭配SQLBuilder使用')
|
159
|
+
|
160
|
+
num = self.exec2one(sql.build_count())
|
161
|
+
cur = self.exec2dict(sql.build_select(), **kwargs)
|
162
|
+
|
163
|
+
def yield_row():
|
164
|
+
while True:
|
165
|
+
rows = cur.fetchmany(batch_size)
|
166
|
+
if not rows:
|
167
|
+
break
|
168
|
+
yield from rows
|
169
|
+
|
170
|
+
return yield_row(), num
|
171
|
+
|
150
172
|
exec_dict = exec2dict
|
151
173
|
|
152
174
|
def __4_数据类型(self):
|
@@ -234,72 +256,83 @@ WHERE {table_name}.{item_id_name} = cte.{item_id_name}"""
|
|
234
256
|
def __6_高级统计(self):
|
235
257
|
pass
|
236
258
|
|
237
|
-
def
|
238
|
-
|
259
|
+
def get_column_valuesstat(self, table_name, column, percentile_count=5,
|
260
|
+
filter_condition=None, by_data=False):
|
239
261
|
""" 获得指定表格的某个字段的统计特征ValuesStat2对象
|
240
262
|
|
241
263
|
:param table_name: 表名
|
242
|
-
:param
|
264
|
+
:param column: 用于计算统计数据的字段名
|
243
265
|
:param percentile_count: 分位数的数量,例如 3 表示只计算中位数
|
244
266
|
:param by_data: 是否获得原始数据
|
245
267
|
默认只获得统计特征,不获得原始数据
|
246
268
|
"""
|
247
269
|
|
248
270
|
def init_from_db_data():
|
249
|
-
|
250
|
-
if
|
271
|
+
sql = SqlBuilder(table_name)
|
272
|
+
if filter_condition:
|
273
|
+
sql.where(filter_condition)
|
274
|
+
values = self.exec2col(sql.build_select(column))
|
275
|
+
if data_type == 'numeric':
|
251
276
|
values = [x and float(x) for x in values]
|
252
|
-
|
253
|
-
return ValuesStat2(raw_values=values)
|
277
|
+
return ValuesStat2(raw_values=values, data_type=data_type)
|
254
278
|
|
255
279
|
def init_from_db():
|
256
|
-
# 构建基础的 SQL 查询
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
280
|
+
# 1 构建基础的 SQL 查询
|
281
|
+
sql = SqlBuilder(table_name)
|
282
|
+
sql.select("COUNT(*) AS total_count")
|
283
|
+
sql.select(f"COUNT({column}) AS non_null_count")
|
284
|
+
sql.select(f"MIN({column}) AS min_value")
|
285
|
+
sql.select(f"MAX({column}) AS max_value")
|
286
|
+
if data_type and 'timestamp' in data_type:
|
287
|
+
percentile_type = 'PERCENTILE_DISC'
|
288
|
+
# todo 其实时间类也可以"泛化"一种平均值、标准差算法的,这需要获取全量数据,然后自己计算
|
289
|
+
elif data_type == 'text':
|
290
|
+
percentile_type = 'PERCENTILE_DISC'
|
291
|
+
else: # 默认是正常的数值类型
|
292
|
+
sql.select(f"SUM({column}) AS total_sum")
|
293
|
+
sql.select(f"AVG({column}) AS average")
|
294
|
+
sql.select(f"STDDEV({column}) AS standard_deviation")
|
295
|
+
percentile_type = 'PERCENTILE_CONT'
|
267
296
|
|
268
297
|
percentiles = []
|
269
298
|
# 根据分位点的数量动态添加分位数计算
|
270
299
|
if percentile_count > 2:
|
271
300
|
step = 1 / (percentile_count - 1)
|
272
301
|
percentiles = [(i * step) for i in range(1, percentile_count - 1)]
|
273
|
-
|
274
|
-
f"
|
275
|
-
|
276
|
-
)
|
277
|
-
sql_query += ", " + percentiles_query
|
302
|
+
for p in percentiles:
|
303
|
+
sql.select(f"{percentile_type}({p:.2f}) WITHIN GROUP (ORDER BY {column}) "
|
304
|
+
f"AS percentile_{int(p * 100)}")
|
278
305
|
|
279
|
-
|
306
|
+
if filter_condition:
|
307
|
+
sql.where(filter_condition)
|
280
308
|
|
281
|
-
|
282
|
-
row = self.exec2dict(sql_query).fetchone()
|
309
|
+
row = self.exec2dict(sql.build_select()).fetchone()
|
283
310
|
|
284
|
-
#
|
285
|
-
x = ValuesStat2()
|
311
|
+
# 2 统计展示
|
312
|
+
x = ValuesStat2(data_type=data_type)
|
286
313
|
x.raw_n = row['total_count']
|
287
314
|
x.n = row['non_null_count']
|
288
|
-
x.
|
289
|
-
|
290
|
-
|
315
|
+
if not x.n:
|
316
|
+
return x
|
317
|
+
|
318
|
+
x.sum = row.get('total_sum', None)
|
319
|
+
x.mean = row.get('average', None)
|
320
|
+
x.std = row.get('standard_deviation', None)
|
291
321
|
|
292
322
|
# 如果计算了分位数,填充相应属性
|
293
323
|
x.dist = [row['min_value']] + [row[f"percentile_{int(p * 100)}"] for p in percentiles] + [row['max_value']]
|
294
|
-
if
|
324
|
+
if data_type == 'numeric':
|
295
325
|
x.dist = [float(x) for x in x.dist]
|
296
326
|
|
297
327
|
return x
|
298
328
|
|
329
|
+
data_type = self.get_column_data_type(table_name, column)
|
299
330
|
if by_data:
|
300
|
-
|
331
|
+
vs = init_from_db_data()
|
301
332
|
else:
|
302
|
-
|
333
|
+
vs = init_from_db()
|
334
|
+
|
335
|
+
return vs
|
303
336
|
|
304
337
|
|
305
338
|
"""
|
@@ -4,6 +4,7 @@
|
|
4
4
|
# @Email : 877362867@qq.com
|
5
5
|
# @Date : 2022/04/12 08:59
|
6
6
|
|
7
|
+
import copy
|
7
8
|
import json
|
8
9
|
import re
|
9
10
|
import sqlite3
|
@@ -18,6 +19,118 @@ warnings.filterwarnings('ignore', message="pandas only support SQLAlchemy connec
|
|
18
19
|
warnings.filterwarnings('ignore', message="pandas only supports SQLAlchemy connectable")
|
19
20
|
|
20
21
|
|
22
|
+
class SqlBuilder:
|
23
|
+
def __init__(self, table=''):
|
24
|
+
self.table = table
|
25
|
+
self._select = []
|
26
|
+
self._set = []
|
27
|
+
self._where = []
|
28
|
+
self._order_by = []
|
29
|
+
self._group_by = []
|
30
|
+
self._limit = None # 限制最多读多少条数据
|
31
|
+
self._offset = None # 从第几条数据开始读
|
32
|
+
|
33
|
+
def copy(self):
|
34
|
+
# 拷贝一个当前状态的副本sql
|
35
|
+
return copy.deepcopy(self)
|
36
|
+
|
37
|
+
def __1_组件(self):
|
38
|
+
pass
|
39
|
+
|
40
|
+
def from_table(self, table):
|
41
|
+
self.table = table
|
42
|
+
return self
|
43
|
+
|
44
|
+
def select(self, *columns):
|
45
|
+
self._select.extend(columns)
|
46
|
+
return self
|
47
|
+
|
48
|
+
def set(self, *columns):
|
49
|
+
self._set.extend(columns)
|
50
|
+
return self
|
51
|
+
|
52
|
+
def where(self, condition):
|
53
|
+
self._where.append(condition)
|
54
|
+
return self
|
55
|
+
|
56
|
+
def where_in(self, column, values):
|
57
|
+
if values is None:
|
58
|
+
return self
|
59
|
+
|
60
|
+
if isinstance(values, str):
|
61
|
+
values = [values]
|
62
|
+
values_str = ', '.join(f"'{str(value)}'" for value in values)
|
63
|
+
if len(values) == 1:
|
64
|
+
self._where.append(f"{column} = {values_str[0]}")
|
65
|
+
else:
|
66
|
+
self._where.append(f"{column} IN ({values_str})")
|
67
|
+
return self
|
68
|
+
|
69
|
+
def where_or(self, *conditions):
|
70
|
+
""" 输入的这一批条件,作为OR组合后成为一个整体条件
|
71
|
+
"""
|
72
|
+
self._where.append(f"({' OR '.join(conditions)})")
|
73
|
+
return self
|
74
|
+
|
75
|
+
def group_by(self, *columns):
|
76
|
+
self._group_by.extend(columns)
|
77
|
+
return self
|
78
|
+
|
79
|
+
def order_by(self, *columns):
|
80
|
+
self._order_by.extend(columns)
|
81
|
+
return self
|
82
|
+
|
83
|
+
def limit(self, limit, offset=None):
|
84
|
+
self._limit = limit
|
85
|
+
self._offset = offset
|
86
|
+
return self
|
87
|
+
|
88
|
+
def __2_build_命令(self):
|
89
|
+
pass
|
90
|
+
|
91
|
+
def build_select(self, *columns):
|
92
|
+
if columns:
|
93
|
+
columns = self._select + list(columns)
|
94
|
+
else:
|
95
|
+
columns = self._select
|
96
|
+
|
97
|
+
sql = [f"SELECT {', '.join(columns) or '*'}", f"FROM {self.table}"]
|
98
|
+
if self._where:
|
99
|
+
sql.append(f"WHERE {' AND '.join(self._where)}")
|
100
|
+
if self._group_by:
|
101
|
+
sql.append(f"GROUP BY {', '.join(self._group_by)}")
|
102
|
+
if self._order_by:
|
103
|
+
sql.append(f"ORDER BY {', '.join(self._order_by)}")
|
104
|
+
if self._limit is not None:
|
105
|
+
limit_clause = f"LIMIT {self._limit}"
|
106
|
+
if self._offset is not None:
|
107
|
+
limit_clause += f" OFFSET {self._offset}"
|
108
|
+
sql.append(limit_clause)
|
109
|
+
return '\n'.join(sql)
|
110
|
+
|
111
|
+
def build_count(self):
|
112
|
+
sql = [f"SELECT COUNT(*)", f"FROM {self.table}"]
|
113
|
+
if self._where:
|
114
|
+
sql.append(f"WHERE {' AND '.join(self._where)}")
|
115
|
+
if self._group_by:
|
116
|
+
sql.append(f"GROUP BY {', '.join(self._group_by)}")
|
117
|
+
return '\n'.join(sql)
|
118
|
+
|
119
|
+
def build_update(self):
|
120
|
+
sql = [f"UPDATE {self.table}"]
|
121
|
+
if self._set:
|
122
|
+
sql.append(f"SET {', '.join(self._set)}")
|
123
|
+
if self._where:
|
124
|
+
sql.append(f"WHERE {' AND '.join(self._where)}")
|
125
|
+
return '\n'.join(sql)
|
126
|
+
|
127
|
+
def build_check_data_type(self, column):
|
128
|
+
sql = SqlBuilder('information_schema.columns')
|
129
|
+
sql.select(f"data_type")
|
130
|
+
sql.where(f"table_name='{self.table}' AND column_name='{column}'")
|
131
|
+
return sql.build_select()
|
132
|
+
|
133
|
+
|
21
134
|
class SqlBase:
|
22
135
|
""" Sql语法通用的功能 """
|
23
136
|
|
@@ -285,6 +398,10 @@ class SqlBase:
|
|
285
398
|
print("No 'FROM' keyword found in the data query.")
|
286
399
|
return 0
|
287
400
|
|
401
|
+
def get_column_data_type(self, table_name, col_name):
|
402
|
+
""" 获取表格中某一列的数据类型 """
|
403
|
+
return self.exec2one(SqlBuilder(table_name).build_check_data_type(col_name))
|
404
|
+
|
288
405
|
|
289
406
|
class Connection(sqlite3.Connection, SqlBase):
|
290
407
|
"""
|
@@ -1437,9 +1437,9 @@ class XlPath(type(pathlib.Path())):
|
|
1437
1437
|
dst = XlPath(dst)
|
1438
1438
|
if dst.exist_preprcs(if_exists):
|
1439
1439
|
if self.is_file():
|
1440
|
-
shutil.copy2(self, dst)
|
1440
|
+
return shutil.copy2(self, dst)
|
1441
1441
|
else:
|
1442
|
-
shutil.copytree(self, dst)
|
1442
|
+
return shutil.copytree(self, dst)
|
1443
1443
|
|
1444
1444
|
def move(self, dst, if_exists=None):
|
1445
1445
|
if not self.exists():
|
@@ -1465,7 +1465,9 @@ class XlPath(type(pathlib.Path())):
|
|
1465
1465
|
if not self.exists():
|
1466
1466
|
return self
|
1467
1467
|
|
1468
|
-
if
|
1468
|
+
if not isinstance(new_name, str):
|
1469
|
+
raise ValueError(f'rename2只能做重命名操作,目标路径必须是一个str')
|
1470
|
+
elif '/' in new_name:
|
1469
1471
|
raise ValueError(f'rename2只能做重命名操作,目标路径中不能包含"/"')
|
1470
1472
|
elif '\\' in new_name:
|
1471
1473
|
raise ValueError(f'rename2只能做重命名操作,目标路径中不能包含"\\"')
|
@@ -1485,6 +1487,14 @@ class XlPath(type(pathlib.Path())):
|
|
1485
1487
|
self.rename(dst)
|
1486
1488
|
return dst
|
1487
1489
|
|
1490
|
+
def rename_stem(self, stem, if_exists=None):
|
1491
|
+
""" 重命名文件的stem """
|
1492
|
+
return self.rename2(stem + self.suffix, if_exists)
|
1493
|
+
|
1494
|
+
def rename_suffix(self, suffix, if_exists=None):
|
1495
|
+
""" 重命名文件的suffix """
|
1496
|
+
return self.rename2(self.stem + suffix, if_exists)
|
1497
|
+
|
1488
1498
|
def delete(self):
|
1489
1499
|
if self.is_file():
|
1490
1500
|
os.remove(self)
|
@@ -2504,34 +2514,55 @@ class DirsFileFinder:
|
|
2504
2514
|
for d in dirs:
|
2505
2515
|
self.add_dir(d)
|
2506
2516
|
|
2507
|
-
def add_dir(self, p):
|
2517
|
+
def add_dir(self, p, cvt_name_func=None):
|
2508
2518
|
""" 添加备用检索目录
|
2509
2519
|
当前面的目录找不到匹配项的时候,会使用备用目录的文件
|
2510
2520
|
备用目录可以一直添加,有多个,优先级逐渐降低
|
2521
|
+
|
2522
|
+
:param cvt_name_func: 对名称做个转换再匹配
|
2511
2523
|
"""
|
2512
2524
|
files = list(XlPath(p).rglob_files())
|
2513
|
-
|
2514
|
-
|
2515
|
-
|
2525
|
+
if cvt_name_func:
|
2526
|
+
for f in files:
|
2527
|
+
self.names[cvt_name_func(f.name)].append(f)
|
2528
|
+
self.stems[cvt_name_func(f.stem)].append(f)
|
2529
|
+
else:
|
2530
|
+
for f in files:
|
2531
|
+
self.names[f.name].append(f)
|
2532
|
+
self.stems[f.stem].append(f)
|
2516
2533
|
|
2517
2534
|
def find_name(self, name):
|
2518
2535
|
""" 返回第一个匹配的结果 """
|
2519
|
-
|
2520
|
-
if
|
2521
|
-
return
|
2536
|
+
files = self.find_names(name)
|
2537
|
+
if files:
|
2538
|
+
return files[0]
|
2522
2539
|
|
2523
2540
|
def find_names(self, name):
|
2524
2541
|
""" 返回所有匹配的结果 """
|
2525
2542
|
return self.names[name]
|
2526
2543
|
|
2527
2544
|
def find_stem(self, stem):
|
2528
|
-
|
2529
|
-
if
|
2530
|
-
return
|
2545
|
+
files = self.find_stems(stem)
|
2546
|
+
if files:
|
2547
|
+
return files[0]
|
2531
2548
|
|
2532
2549
|
def find_stems(self, stem):
|
2533
2550
|
return self.stems[stem]
|
2534
2551
|
|
2552
|
+
def find_prefix_name(self, prefix_name, suffix=None):
|
2553
|
+
files = self.find_prefix_names(prefix_name, suffix=suffix)
|
2554
|
+
if files:
|
2555
|
+
return files[0]
|
2556
|
+
|
2557
|
+
def find_prefix_names(self, prefix_name, suffix=None):
|
2558
|
+
""" name中前缀为prefix_name """
|
2559
|
+
filess = [files for name, files in self.names.items() if name.startswith(prefix_name)]
|
2560
|
+
# 将嵌套的list展平
|
2561
|
+
files = [file for files in filess for file in files]
|
2562
|
+
if suffix:
|
2563
|
+
files = [file for file in files if file.suffix == suffix]
|
2564
|
+
return files
|
2565
|
+
|
2535
2566
|
|
2536
2567
|
class TwinDirs:
|
2537
2568
|
def __init__(self, src_dir, dst_dir):
|
@@ -259,6 +259,9 @@ def human_readable_number(value, base_type='K', precision=4):
|
|
259
259
|
:param str base_type: 进制类型,'K'为1000进制, 'KB'为1024进制(KiB同理), '万'为中文万进制
|
260
260
|
:return: 美化后的字符串
|
261
261
|
"""
|
262
|
+
if value is None:
|
263
|
+
return ''
|
264
|
+
|
262
265
|
if abs(value) < 1:
|
263
266
|
return f'{value:.{precision}g}'
|
264
267
|
|
@@ -16,7 +16,10 @@ from pyxllib.file.specialist import File, Dir, filesmatch, get_encoding, XlPath
|
|
16
16
|
# BCompare.exe, bcompare函数要用
|
17
17
|
|
18
18
|
class BCompare(Explorer):
|
19
|
-
def __init__(self, app='
|
19
|
+
def __init__(self, app='bcomp', shell=False):
|
20
|
+
"""
|
21
|
+
240512周日20:06,本来写的是BCompare,但是友鑫mac电脑上发现似乎有问题,所以改成bcomp,这种在windows上也能用
|
22
|
+
"""
|
20
23
|
super().__init__(app, shell)
|
21
24
|
|
22
25
|
@classmethod
|
@@ -48,7 +51,7 @@ class BCompare(Explorer):
|
|
48
51
|
default_suffix = None
|
49
52
|
for i, arg in enumerate(args):
|
50
53
|
f = XlPath.safe_init(arg)
|
51
|
-
if f.is_file(): # 是文件对象,且存在
|
54
|
+
if f is not None and f.is_file(): # 是文件对象,且存在
|
52
55
|
new_args.append(f)
|
53
56
|
if not default_suffix:
|
54
57
|
default_suffix = f.suffix
|