pyxllib 0.3.143__tar.gz → 0.3.147__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.143/pyxllib.egg-info → pyxllib-0.3.147}/PKG-INFO +17 -17
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/autogui/uiautolib.py +23 -10
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/autogui/wechat.py +3 -3
- pyxllib-0.3.147/pyxllib/prog/filelock.py +141 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/prog/multiprogs.py +273 -39
- {pyxllib-0.3.143 → pyxllib-0.3.147/pyxllib.egg-info}/PKG-INFO +17 -17
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib.egg-info/SOURCES.txt +1 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/setup.py +1 -1
- {pyxllib-0.3.143 → pyxllib-0.3.147}/LICENSE +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/MANIFEST.in +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/README.md +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/__init__.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/algo/__init__.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/algo/disjoint.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/algo/geo.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/algo/intervals.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/algo/matcher.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/algo/newbie.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/algo/pupil.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/algo/shapelylib.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/algo/specialist.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/algo/stat.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/algo/treelib.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/algo/unitlib.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/autogui/__init__.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/autogui/activewin.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/autogui/all.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/autogui/autogui.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/autogui/virtualkey.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/autogui/wechat_msg.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/cv/__init__.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/cv/expert.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/cv/imfile.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/cv/imhash.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/cv/pupil.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/cv/rgbfmt.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/cv/trackbartools.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/cv/xlcvlib.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/cv/xlpillib.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/data/__init__.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/data/echarts.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/data/jsonlib.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/data/oss.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/data/pglib.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/data/sqlite.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/data/sqllib.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/ext/JLineViewer.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/ext/__init__.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/ext/demolib.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/ext/drissionlib.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/ext/kq5034lib.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/ext/old.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/ext/qt.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/ext/robustprocfile.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/ext/seleniumlib.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/ext/tk.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/ext/unixlib.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/ext/utools.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/ext/webhook.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/ext/win32lib.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/ext/yuquelib.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/file/__init__.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/file/docxlib.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/file/gitlib.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/file/libreoffice.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/file/movielib.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/file/newbie.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/file/onenotelib.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/file/packlib/__init__.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/file/packlib/zipfile.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/file/pdflib.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/file/pupil.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/file/specialist/__init__.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/file/specialist/dirlib.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/file/specialist/download.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/file/specialist/filelib.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/file/xlsxlib.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/file/xlsyncfile.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/prog/__init__.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/prog/cachetools.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/prog/deprecatedlib.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/prog/ipyexec.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/prog/newbie.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/prog/pupil.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/prog/sitepackages.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/prog/specialist/__init__.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/prog/specialist/bc.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/prog/specialist/browser.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/prog/specialist/common.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/prog/specialist/datetime.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/prog/specialist/tictoc.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/prog/specialist/xllog.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/prog/xlosenv.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/stdlib/__init__.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/stdlib/tablepyxl/__init__.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/stdlib/tablepyxl/style.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/stdlib/tablepyxl/tablepyxl.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/text/__init__.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/text/ahocorasick.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/text/charclasslib.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/text/jiebalib.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/text/jinjalib.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/text/jscode.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/text/latex/__init__.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/text/levenshtein.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/text/nestenv.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/text/newbie.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/text/pupil/__init__.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/text/pupil/common.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/text/pupil/xlalign.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/text/pycode.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/text/specialist/__init__.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/text/specialist/common.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/text/specialist/ptag.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/text/spellchecker.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/text/templates/echart_base.html +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/text/templates/highlight_code.html +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/text/templates/latex_editor.html +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/text/vbacode.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/text/xmllib.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/xl.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib/xlcv.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib.egg-info/dependency_links.txt +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib.egg-info/requires.txt +16 -16
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxllib.egg-info/top_level.txt +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/__init__.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ai/__init__.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ai/clientlib.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ai/specialist.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ai/torch_app.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ai/xlpaddle.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ai/xltorch.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/data/__init__.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/data/coco.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/data/datacls.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/data/datasets.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/data/gptlib.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/data/icdar/__init__.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/data/icdar/deteval.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/data/icdar/icdar2013.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/data/icdar/iou.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/data/icdar/rrc_evaluation_funcs_1_1.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/data/imtextline.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/data/labelme.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/data/removeline.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/data/specialist.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/data/tiktokenlib.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/eval/__init__.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/openai2/__init__.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/openai2/_core/chat.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/openai2/_core/chat_in_cmd.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/openai2/_core/group_chat.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/openai2/openai2.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/paddleocr.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/__init__.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/configs/rec/multi_language/generate_multi_language_configs.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/data/__init__.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/data/imaug/ColorJitter.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/data/imaug/__init__.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/data/imaug/copy_paste.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/data/imaug/east_process.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/data/imaug/gen_table_mask.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/data/imaug/iaa_augment.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/data/imaug/label_ops.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/data/imaug/make_border_map.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/data/imaug/make_pse_gt.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/data/imaug/make_shrink_map.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/data/imaug/operators.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/data/imaug/pg_process.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/data/imaug/randaugment.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/data/imaug/random_crop_data.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/data/imaug/rec_img_aug.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/data/imaug/sast_process.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/data/imaug/text_image_aug/__init__.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/data/imaug/text_image_aug/augment.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/data/imaug/text_image_aug/warp_mls.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/data/lmdb_dataset.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/data/pgnet_dataset.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/data/pubtab_dataset.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/data/simple_dataset.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/losses/__init__.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/losses/ace_loss.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/losses/basic_loss.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/losses/center_loss.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/losses/cls_loss.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/losses/combined_loss.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/losses/det_basic_loss.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/losses/det_db_loss.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/losses/det_east_loss.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/losses/det_pse_loss.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/losses/det_sast_loss.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/losses/distillation_loss.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/losses/e2e_pg_loss.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/losses/kie_sdmgr_loss.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/losses/rec_aster_loss.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/losses/rec_att_loss.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/losses/rec_ctc_loss.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/losses/rec_enhanced_ctc_loss.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/losses/rec_nrtr_loss.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/losses/rec_sar_loss.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/losses/rec_srn_loss.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/losses/table_att_loss.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/metrics/__init__.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/metrics/cls_metric.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/metrics/det_metric.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/metrics/distillation_metric.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/metrics/e2e_metric.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/metrics/eval_det_iou.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/metrics/kie_metric.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/metrics/rec_metric.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/metrics/table_metric.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/modeling/architectures/__init__.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/modeling/architectures/base_model.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/modeling/architectures/distillation_model.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/modeling/backbones/__init__.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/modeling/backbones/det_mobilenet_v3.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/modeling/backbones/det_resnet_vd.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/modeling/backbones/det_resnet_vd_sast.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/modeling/backbones/e2e_resnet_vd_pg.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/modeling/backbones/kie_unet_sdmgr.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/modeling/backbones/rec_mobilenet_v3.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/modeling/backbones/rec_mv1_enhance.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/modeling/backbones/rec_nrtr_mtb.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/modeling/backbones/rec_resnet_31.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/modeling/backbones/rec_resnet_aster.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/modeling/backbones/rec_resnet_fpn.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/modeling/backbones/rec_resnet_vd.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/modeling/heads/__init__.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/modeling/heads/cls_head.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/modeling/heads/det_db_head.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/modeling/heads/det_east_head.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/modeling/heads/det_pse_head.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/modeling/heads/det_sast_head.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/modeling/heads/e2e_pg_head.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/modeling/heads/kie_sdmgr_head.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/modeling/heads/multiheadAttention.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/modeling/heads/rec_aster_head.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/modeling/heads/rec_att_head.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/modeling/heads/rec_ctc_head.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/modeling/heads/rec_nrtr_head.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/modeling/heads/rec_sar_head.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/modeling/heads/rec_srn_head.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/modeling/heads/self_attention.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/modeling/heads/table_att_head.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/modeling/necks/__init__.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/modeling/necks/db_fpn.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/modeling/necks/east_fpn.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/modeling/necks/fpn.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/modeling/necks/pg_fpn.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/modeling/necks/rnn.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/modeling/necks/sast_fpn.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/modeling/necks/table_fpn.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/modeling/transforms/__init__.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/modeling/transforms/stn.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/modeling/transforms/tps.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/modeling/transforms/tps_spatial_transformer.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/optimizer/__init__.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/optimizer/learning_rate.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/optimizer/lr_scheduler.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/optimizer/optimizer.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/optimizer/regularizer.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/postprocess/__init__.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/postprocess/cls_postprocess.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/postprocess/db_postprocess.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/postprocess/east_postprocess.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/postprocess/locality_aware_nms.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/postprocess/pg_postprocess.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/postprocess/pse_postprocess/__init__.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/postprocess/pse_postprocess/pse/__init__.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/postprocess/pse_postprocess/pse/setup.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/postprocess/pse_postprocess/pse_postprocess.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/postprocess/rec_postprocess.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/postprocess/sast_postprocess.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/tools/__init__.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/tools/eval.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/tools/export_center.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/tools/export_model.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/tools/infer/predict_cls.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/tools/infer/predict_det.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/tools/infer/predict_e2e.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/tools/infer/predict_rec.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/tools/infer/predict_system.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/tools/infer/utility.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/tools/infer_cls.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/tools/infer_det.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/tools/infer_e2e.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/tools/infer_kie.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/tools/infer_rec.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/tools/infer_table.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/tools/program.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/tools/test_hubserving.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/tools/train.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/tools/xlprog.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/utils/EN_symbol_dict.txt +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/utils/__init__.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/utils/dict/ar_dict.txt +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/utils/dict/arabic_dict.txt +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/utils/dict/be_dict.txt +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/utils/dict/bg_dict.txt +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/utils/dict/chinese_cht_dict.txt +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/utils/dict/cyrillic_dict.txt +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/utils/dict/devanagari_dict.txt +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/utils/dict/en_dict.txt +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/utils/dict/fa_dict.txt +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/utils/dict/french_dict.txt +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/utils/dict/german_dict.txt +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/utils/dict/hi_dict.txt +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/utils/dict/it_dict.txt +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/utils/dict/japan_dict.txt +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/utils/dict/ka_dict.txt +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/utils/dict/korean_dict.txt +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/utils/dict/latin_dict.txt +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/utils/dict/mr_dict.txt +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/utils/dict/ne_dict.txt +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/utils/dict/oc_dict.txt +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/utils/dict/pu_dict.txt +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/utils/dict/rs_dict.txt +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/utils/dict/rsc_dict.txt +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/utils/dict/ru_dict.txt +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/utils/dict/ta_dict.txt +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/utils/dict/table_dict.txt +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/utils/dict/table_structure_dict.txt +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/utils/dict/te_dict.txt +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/utils/dict/ug_dict.txt +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/utils/dict/uk_dict.txt +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/utils/dict/ur_dict.txt +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/utils/dict/xi_dict.txt +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/utils/dict90.txt +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/utils/e2e_metric/Deteval.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/utils/e2e_metric/polygon_fast.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/utils/e2e_utils/extract_batchsize.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/utils/e2e_utils/extract_textpoint_fast.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/utils/e2e_utils/extract_textpoint_slow.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/utils/e2e_utils/pgnet_pp_utils.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/utils/e2e_utils/visual.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/utils/en_dict.txt +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/utils/gen_label.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/utils/ic15_dict.txt +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/utils/iou.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/utils/logging.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/utils/network.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/utils/ppocr_keys_v1.txt +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/utils/profiler.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/utils/save_load.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/utils/stats.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppocr/utils/utility.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppstructure/__init__.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppstructure/predict_system.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppstructure/table/__init__.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppstructure/table/eval_table.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppstructure/table/matcher.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppstructure/table/predict_structure.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppstructure/table/predict_table.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppstructure/table/table_metric/__init__.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppstructure/table/table_metric/parallel.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppstructure/table/table_metric/table_metric.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppstructure/table/tablepyxl/__init__.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppstructure/table/tablepyxl/style.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppstructure/table/tablepyxl/tablepyxl.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/ppstructure/utility.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/pyxlpr/xlai.py +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/requirements.txt +0 -0
- {pyxllib-0.3.143 → pyxllib-0.3.147}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: pyxllib
|
3
|
-
Version: 0.3.
|
3
|
+
Version: 0.3.147
|
4
4
|
Summary: 厦门理工模式识别团队通用python代码工具库
|
5
5
|
Home-page: https://github.com/XLPRUtils/pyxllib
|
6
6
|
Author: code4101
|
@@ -38,33 +38,33 @@ Requires-Dist: Jinja2
|
|
38
38
|
Requires-Dist: pandas>=0.23.4
|
39
39
|
Requires-Dist: pillow
|
40
40
|
Provides-Extra: xlcv
|
41
|
-
Requires-Dist: opencv-python; extra == "xlcv"
|
42
|
-
Requires-Dist: pillow; extra == "xlcv"
|
43
41
|
Requires-Dist: opsdroid-get-image-size; extra == "xlcv"
|
42
|
+
Requires-Dist: pillow; extra == "xlcv"
|
43
|
+
Requires-Dist: opencv-python; extra == "xlcv"
|
44
44
|
Provides-Extra: xlai
|
45
|
-
Requires-Dist: opsdroid-get-image-size; extra == "xlai"
|
46
|
-
Requires-Dist: opencv-python; extra == "xlai"
|
47
|
-
Requires-Dist: pillow; extra == "xlai"
|
48
45
|
Requires-Dist: pynvml; extra == "xlai"
|
49
46
|
Requires-Dist: visdom; extra == "xlai"
|
47
|
+
Requires-Dist: pillow; extra == "xlai"
|
48
|
+
Requires-Dist: opsdroid-get-image-size; extra == "xlai"
|
49
|
+
Requires-Dist: opencv-python; extra == "xlai"
|
50
50
|
Provides-Extra: xlall
|
51
|
-
Requires-Dist: flask-cors; extra == "xlall"
|
52
|
-
Requires-Dist: fastapi; extra == "xlall"
|
53
|
-
Requires-Dist: flask-jwt-extended; extra == "xlall"
|
54
51
|
Requires-Dist: ujson; extra == "xlall"
|
52
|
+
Requires-Dist: flask; extra == "xlall"
|
53
|
+
Requires-Dist: html2text; extra == "xlall"
|
55
54
|
Requires-Dist: zhconv; extra == "xlall"
|
56
|
-
Requires-Dist: opsdroid-get-image-size; extra == "xlall"
|
57
|
-
Requires-Dist: openai2; extra == "xlall"
|
58
|
-
Requires-Dist: opencv-python; extra == "xlall"
|
59
55
|
Requires-Dist: arts; extra == "xlall"
|
60
|
-
Requires-Dist:
|
61
|
-
Requires-Dist:
|
62
|
-
Requires-Dist: sentencepiece; extra == "xlall"
|
56
|
+
Requires-Dist: xlrd; extra == "xlall"
|
57
|
+
Requires-Dist: flask-cors; extra == "xlall"
|
63
58
|
Requires-Dist: flask-restful; extra == "xlall"
|
64
59
|
Requires-Dist: flask-wtf; extra == "xlall"
|
60
|
+
Requires-Dist: fastapi; extra == "xlall"
|
61
|
+
Requires-Dist: pillow; extra == "xlall"
|
62
|
+
Requires-Dist: sentencepiece; extra == "xlall"
|
65
63
|
Requires-Dist: uvicorn; extra == "xlall"
|
66
|
-
Requires-Dist:
|
67
|
-
Requires-Dist:
|
64
|
+
Requires-Dist: flask-jwt-extended; extra == "xlall"
|
65
|
+
Requires-Dist: opsdroid-get-image-size; extra == "xlall"
|
66
|
+
Requires-Dist: openai2; extra == "xlall"
|
67
|
+
Requires-Dist: opencv-python; extra == "xlall"
|
68
68
|
|
69
69
|
# 1 install
|
70
70
|
|
@@ -9,13 +9,16 @@
|
|
9
9
|
"""
|
10
10
|
|
11
11
|
import os
|
12
|
+
import sys
|
12
13
|
import textwrap
|
13
14
|
import time
|
14
15
|
from typing import Iterable, Callable, List
|
16
|
+
import subprocess
|
15
17
|
|
16
18
|
import psutil
|
17
19
|
import pandas as pd
|
18
20
|
|
21
|
+
from loguru import logger
|
19
22
|
# ui组件大多是树形组织结构,auto库自带树形操作太弱。没有专业的树形结构库,能搞个毛线。
|
20
23
|
from anytree import NodeMixin
|
21
24
|
|
@@ -236,22 +239,32 @@ class UiCtrlNode(NodeMixin):
|
|
236
239
|
ctrl = find_ctrl(class_name=class_name, name=name, **kwargs)
|
237
240
|
return cls(ctrl, build_depth=build_depth)
|
238
241
|
|
239
|
-
def activate(self):
|
242
|
+
def activate(self, check_seconds=2):
|
240
243
|
""" 激活当前窗口
|
241
|
-
|
242
|
-
todo 修改的更稳定些?多些判断,重复测试,等待?
|
243
244
|
"""
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
245
|
+
while True:
|
246
|
+
hwnd = win32gui.FindWindow(self.ctrl.ClassName, self.text)
|
247
|
+
# logger.info(hwnd)
|
248
|
+
if not hwnd:
|
249
|
+
return
|
250
|
+
|
248
251
|
if win32gui.GetForegroundWindow() != hwnd:
|
249
|
-
|
252
|
+
win32gui.ShowWindow(hwnd, win32con.SW_RESTORE)
|
253
|
+
|
250
254
|
try:
|
251
|
-
|
255
|
+
# 在这里执行SetForegroundWindow,只有程序的第1次运行有效,之后就会被很多全屏类的应用占用最前置,覆盖不了了
|
256
|
+
# 为了解决这问题,就只能暴力每次都新开一个程序来执行这个SetForegroundWindow操作
|
257
|
+
subprocess.run(
|
258
|
+
[sys.executable, "-c", f"import win32gui; win32gui.SetForegroundWindow({hwnd})"],
|
259
|
+
stdout=subprocess.PIPE,
|
260
|
+
)
|
252
261
|
except Exception as e:
|
253
262
|
pass
|
254
|
-
|
263
|
+
# 理论上并不需要等待,但加个等待,有助于稳定性检测,如果当前窗口在check_seconds秒内频繁切换,
|
264
|
+
# 使用activate虽然激活了,但并不安全,只有check_seconds秒内维持稳定在这个窗口,再进行下游任务会更好
|
265
|
+
time.sleep(check_seconds)
|
266
|
+
else:
|
267
|
+
break
|
255
268
|
|
256
269
|
def build_children(self, build_depth=-1, child_node_class=None):
|
257
270
|
""" 创建并添加子节点到树中 """
|
@@ -41,7 +41,7 @@ class WeChatConfig:
|
|
41
41
|
WINDOW_CLASSNAME = 'WeChatMainWndForPC'
|
42
42
|
|
43
43
|
|
44
|
-
WeChat = WeChatConfig
|
44
|
+
# WeChat = WeChatConfig
|
45
45
|
|
46
46
|
|
47
47
|
class IntervalConfig:
|
@@ -496,8 +496,8 @@ class WxOperation:
|
|
496
496
|
|
497
497
|
def locate_wechat_window(self):
|
498
498
|
if not self.visible_flag:
|
499
|
-
wake_up_window(class_name=
|
500
|
-
self.wx_window = auto.WindowControl(Name=
|
499
|
+
wake_up_window(class_name=WeChatConfig.WINDOW_CLASSNAME, name=WeChatConfig.WINDOW_NAME)
|
500
|
+
self.wx_window = auto.WindowControl(Name=WeChatConfig.WINDOW_NAME, ClassName=WeChatConfig.WINDOW_CLASSNAME)
|
501
501
|
if not self.wx_window.Exists(Interval.MAX_SEARCH_SECOND,
|
502
502
|
searchIntervalSeconds=Interval.MAX_SEARCH_INTERVAL):
|
503
503
|
raise Exception('微信似乎并没有登录!')
|
@@ -0,0 +1,141 @@
|
|
1
|
+
#!/usr/bin/env python3
|
2
|
+
# -*- coding: utf-8 -*-
|
3
|
+
# @Author : 陈坤泽
|
4
|
+
# @Email : 877362867@qq.com
|
5
|
+
# @Date : 2024/11/13
|
6
|
+
|
7
|
+
import os
|
8
|
+
import time
|
9
|
+
import platform
|
10
|
+
import tempfile
|
11
|
+
|
12
|
+
if platform.system() == 'Windows':
|
13
|
+
import msvcrt
|
14
|
+
else:
|
15
|
+
import fcntl
|
16
|
+
|
17
|
+
|
18
|
+
class FileLock:
|
19
|
+
"""
|
20
|
+
文件锁类,用于在不同进程之间实现互斥锁,确保同一时间只有一个程序实例可以访问共享资源。
|
21
|
+
|
22
|
+
适用于以下场景:
|
23
|
+
- 防止多个独立程序同时操作同一资源(如文件、窗口、数据库等)。
|
24
|
+
- 解决多个自动化脚本并发访问相同应用程序时的冲突问题。
|
25
|
+
- 跨平台支持:在 Windows 上使用 `msvcrt`,在 Unix 系统上使用 `fcntl`。
|
26
|
+
|
27
|
+
使用方式:
|
28
|
+
1. 作为上下文管理器:
|
29
|
+
>> with FileLock('wechat.lock'):
|
30
|
+
>> # 执行独占的操作
|
31
|
+
>> print("操作微信...")
|
32
|
+
|
33
|
+
2. 手动调用 acquire() 和 release():
|
34
|
+
>> lock = FileLock('wechat.lock')
|
35
|
+
>> try:
|
36
|
+
>> lock.acquire()
|
37
|
+
>> print("正在执行任务...")
|
38
|
+
>> finally:
|
39
|
+
>> lock.release()
|
40
|
+
|
41
|
+
属性:
|
42
|
+
:param bool locked: 指示当前是否已获得文件锁。
|
43
|
+
|
44
|
+
异常:
|
45
|
+
- TimeoutError: 如果在指定的超时时间内无法获取锁,则抛出此异常。
|
46
|
+
"""
|
47
|
+
|
48
|
+
def __init__(self, lock_file='lockfile.lock', timeout=10, check_interval=0.1):
|
49
|
+
"""
|
50
|
+
|
51
|
+
:param str lock_file: 锁文件的路径,默认值为 'lockfile.lock'。
|
52
|
+
:param int timeout: 获取锁的超时时间,单位为秒,默认值为 10 秒。
|
53
|
+
:param float check_interval: 重试获取锁的时间间隔,单位为秒,默认值为 0.1 秒。
|
54
|
+
"""
|
55
|
+
# 如果 lock_file 没有提供绝对路径,则将其存储在临时目录下
|
56
|
+
if not os.path.isabs(lock_file):
|
57
|
+
lock_file = os.path.join(tempfile.gettempdir(), lock_file)
|
58
|
+
|
59
|
+
self.lock_file = lock_file
|
60
|
+
self.timeout = timeout
|
61
|
+
self.check_interval = check_interval
|
62
|
+
self.locked = False
|
63
|
+
self.file = None
|
64
|
+
|
65
|
+
def acquire(self):
|
66
|
+
"""
|
67
|
+
手动获取文件锁。
|
68
|
+
|
69
|
+
如果文件已被其他进程锁定,则会阻塞,直到成功获取锁或者超时。
|
70
|
+
如果在指定的超时时间内无法获取锁,则抛出 TimeoutError。
|
71
|
+
|
72
|
+
Raises:
|
73
|
+
TimeoutError: 如果在指定的超时时间内无法获取锁。
|
74
|
+
"""
|
75
|
+
start_time = time.time()
|
76
|
+
while True:
|
77
|
+
try:
|
78
|
+
self.file = open(self.lock_file, 'w')
|
79
|
+
if platform.system() == 'Windows':
|
80
|
+
# Windows 系统使用 msvcrt.locking() 实现文件锁
|
81
|
+
msvcrt.locking(self.file.fileno(), msvcrt.LK_NBLCK, 1)
|
82
|
+
else:
|
83
|
+
# Unix 系统使用 fcntl.flock() 实现文件锁
|
84
|
+
fcntl.flock(self.file, fcntl.LOCK_EX | fcntl.LOCK_NB)
|
85
|
+
self.locked = True
|
86
|
+
break
|
87
|
+
except (BlockingIOError, OSError):
|
88
|
+
if time.time() - start_time > self.timeout:
|
89
|
+
raise TimeoutError(f"无法在 {self.timeout} 秒内获取文件锁:{self.lock_file}")
|
90
|
+
time.sleep(self.check_interval)
|
91
|
+
|
92
|
+
def release(self):
|
93
|
+
"""
|
94
|
+
手动释放文件锁。
|
95
|
+
|
96
|
+
如果锁已被获取,则解锁并关闭文件句柄。
|
97
|
+
"""
|
98
|
+
if self.locked and self.file:
|
99
|
+
if platform.system() == 'Windows':
|
100
|
+
# Windows 系统释放锁
|
101
|
+
msvcrt.locking(self.file.fileno(), msvcrt.LK_UNLCK, 1)
|
102
|
+
else:
|
103
|
+
# Unix 系统释放锁
|
104
|
+
fcntl.flock(self.file, fcntl.LOCK_UN)
|
105
|
+
self.file.close()
|
106
|
+
self.locked = False
|
107
|
+
|
108
|
+
def __enter__(self):
|
109
|
+
"""
|
110
|
+
进入上下文管理器时自动获取文件锁。
|
111
|
+
|
112
|
+
Returns:
|
113
|
+
self: 返回当前 FileLock 实例。
|
114
|
+
"""
|
115
|
+
self.acquire()
|
116
|
+
return self
|
117
|
+
|
118
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
119
|
+
"""
|
120
|
+
退出上下文管理器时自动释放文件锁。
|
121
|
+
"""
|
122
|
+
self.release()
|
123
|
+
|
124
|
+
|
125
|
+
# 示例:如何使用 FileLock 类
|
126
|
+
if __name__ == '__main__':
|
127
|
+
# 使用上下文管理器
|
128
|
+
with FileLock('wechat.lock') as lock:
|
129
|
+
print("通过上下文管理器获取锁,正在操作微信...")
|
130
|
+
time.sleep(3)
|
131
|
+
print("操作完成")
|
132
|
+
|
133
|
+
# 手动调用 acquire 和 release
|
134
|
+
lock = FileLock('wechat.lock')
|
135
|
+
try:
|
136
|
+
lock.acquire()
|
137
|
+
print("手动获取锁,正在执行任务...")
|
138
|
+
time.sleep(3)
|
139
|
+
finally:
|
140
|
+
lock.release()
|
141
|
+
print("任务完成并已释放锁")
|
@@ -4,6 +4,7 @@
|
|
4
4
|
# @Email : 877362867@qq.com
|
5
5
|
# @Date : 2024/11/12
|
6
6
|
|
7
|
+
from collections import defaultdict
|
7
8
|
from types import SimpleNamespace
|
8
9
|
from unittest.mock import Mock
|
9
10
|
import ctypes
|
@@ -13,13 +14,20 @@ import socketserver
|
|
13
14
|
import subprocess
|
14
15
|
import sys
|
15
16
|
import time
|
16
|
-
import
|
17
|
+
import textwrap
|
18
|
+
import threading
|
17
19
|
|
18
20
|
from deprecated import deprecated
|
19
21
|
from loguru import logger
|
20
22
|
from croniter import croniter
|
23
|
+
import pandas as pd
|
24
|
+
|
25
|
+
from fastapi import FastAPI
|
26
|
+
from fastapi.responses import PlainTextResponse
|
21
27
|
|
22
28
|
from pyxllib.prog.specialist import parse_datetime
|
29
|
+
from pyxllib.algo.stat import print_full_dataframe
|
30
|
+
from pyxllib.file.specialist import XlPath
|
23
31
|
|
24
32
|
|
25
33
|
def __1_定时工具():
|
@@ -202,10 +210,18 @@ class ProgramWorker(SimpleNamespace):
|
|
202
210
|
proc.pid = None
|
203
211
|
proc.poll.return_value = 'tag'
|
204
212
|
self.program = proc
|
205
|
-
|
206
|
-
|
213
|
+
return self.program
|
214
|
+
|
215
|
+
kwargs = {}
|
216
|
+
for name in ['stdin', 'stdout', 'stderr']:
|
217
|
+
if hasattr(self, name):
|
218
|
+
kwargs[name] = getattr(self, name)
|
219
|
+
|
220
|
+
if sys.platform == 'win32':
|
221
|
+
self.program = subprocess.Popen(self.cmd, shell=self.shell, **kwargs)
|
207
222
|
else:
|
208
|
-
self.program = subprocess.Popen(self.cmd, shell=self.shell,
|
223
|
+
self.program = subprocess.Popen(self.cmd, shell=self.shell, **kwargs,
|
224
|
+
preexec_fn=self._set_pdeathsig())
|
209
225
|
|
210
226
|
return self.program
|
211
227
|
|
@@ -249,6 +265,7 @@ class MultiProgramLauncher:
|
|
249
265
|
|
250
266
|
def init_scheduler(self):
|
251
267
|
from apscheduler.schedulers.background import BackgroundScheduler
|
268
|
+
# from apscheduler.schedulers.asyncio import AsyncIOScheduler
|
252
269
|
|
253
270
|
if self.scheduler is None:
|
254
271
|
self.scheduler = BackgroundScheduler()
|
@@ -320,9 +337,9 @@ class MultiProgramLauncher:
|
|
320
337
|
elif isinstance(schedule, str):
|
321
338
|
from apscheduler.triggers.cron import CronTrigger
|
322
339
|
cron_parts = schedule.split()
|
323
|
-
# 如果是 5 个字段,则补齐 "秒" 字段为 '
|
340
|
+
# 如果是 5 个字段,则补齐 "秒" 字段为 '0'
|
324
341
|
if len(cron_parts) == 5:
|
325
|
-
cron_parts.insert(0, '
|
342
|
+
cron_parts.insert(0, '0')
|
326
343
|
# 检查是否为有效的 6 字段 cron 表达式
|
327
344
|
if len(cron_parts) == 6:
|
328
345
|
# 统一处理为 6 字段格式
|
@@ -389,9 +406,6 @@ class MultiProgramLauncher:
|
|
389
406
|
|
390
407
|
return worker
|
391
408
|
|
392
|
-
def __2_各种添加进程的机制(self):
|
393
|
-
pass
|
394
|
-
|
395
409
|
def add_program_cmd2(self, cmd, ports=1, name=None, **kwargs):
|
396
410
|
"""
|
397
411
|
增强版 add_program_cmd,支持 ports 的处理
|
@@ -452,6 +466,9 @@ class MultiProgramLauncher:
|
|
452
466
|
|
453
467
|
return workers
|
454
468
|
|
469
|
+
def __2_各种添加进程的机制(self):
|
470
|
+
pass
|
471
|
+
|
455
472
|
def add_program_python(self, py_file, args='',
|
456
473
|
ports=None, locations=None,
|
457
474
|
name=None, shell=False, executer=None,
|
@@ -487,11 +504,152 @@ class MultiProgramLauncher:
|
|
487
504
|
cmd.append(args)
|
488
505
|
else:
|
489
506
|
cmd += list(args)
|
507
|
+
if name is None:
|
508
|
+
name = module
|
490
509
|
return self.add_program_cmd3(cmd, ports=ports, name=name, locations=locations, shell=shell, **kwargs)
|
491
510
|
|
492
|
-
def
|
511
|
+
def add_prog(self, prog, extcmds='',
|
512
|
+
ports=None, locations=None, *,
|
513
|
+
name=None, devices=None,
|
514
|
+
executer=None,
|
515
|
+
run=True,
|
516
|
+
schedule=None,
|
517
|
+
):
|
518
|
+
"""
|
519
|
+
:param int|list ports:
|
520
|
+
:param str|list extcmds:
|
521
|
+
"""
|
522
|
+
if locations is None:
|
523
|
+
locations = f'/api/{prog.split('.')[-1]}'
|
524
|
+
self.add_program_python_module(prog,
|
525
|
+
extcmds,
|
526
|
+
ports=ports, locations=locations,
|
527
|
+
name=name, devices=devices,
|
528
|
+
executer=executer,
|
529
|
+
run=run,
|
530
|
+
schedule=schedule,
|
531
|
+
)
|
532
|
+
|
533
|
+
def add_server(self, prog, ports=None, locations=None, *args, **kwargs):
|
534
|
+
""" 我自己部署的服务,基本都有特定的start_server启动函数 """
|
535
|
+
self.add_prog(prog, extcmds='start_server', ports=ports, locations=locations, *args, **kwargs)
|
536
|
+
|
537
|
+
def add_os_command_task(self,
|
538
|
+
script_content,
|
539
|
+
extension=None,
|
540
|
+
shell=False,
|
541
|
+
run=True,
|
542
|
+
name=None,
|
543
|
+
schedule=None,
|
544
|
+
**kwargs):
|
545
|
+
"""
|
546
|
+
添加一个操作系统命令或脚本(如 .bat、.sh、.ps1 等)并启动。
|
547
|
+
|
548
|
+
:param script_content: 脚本的内容(字符串)
|
549
|
+
:param extension: 脚本文件的扩展名(如 .bat, .sh, .ps1);如果为 None 则根据操作系统自动选择
|
550
|
+
:param shell: 是否使用 shell 执行
|
551
|
+
:param run: 是否立即启动
|
552
|
+
:param name: 程序名称
|
553
|
+
:param schedule: 定时任务配置
|
554
|
+
"""
|
555
|
+
# 1 自动选择脚本文件扩展名
|
556
|
+
if extension is None:
|
557
|
+
if sys.platform == 'win32':
|
558
|
+
extension = '.ps1' # Windows 默认使用 PowerShell
|
559
|
+
else:
|
560
|
+
extension = '.sh' # Linux 和 macOS 默认使用 Bash
|
561
|
+
|
562
|
+
# 2 添加编码配置到脚本内容
|
563
|
+
if extension == '.bat':
|
564
|
+
# 为 .bat 文件添加 UTF-8 支持
|
565
|
+
script_content = f"chcp 65001 >nul\n{script_content}"
|
566
|
+
elif extension == '.ps1':
|
567
|
+
# 为 .ps1 文件添加 UTF-8 支持
|
568
|
+
script_content = f"[Console]::OutputEncoding = [System.Text.Encoding]::UTF8\n" \
|
569
|
+
f"[Console]::InputEncoding = [System.Text.Encoding]::UTF8\n{script_content}"
|
570
|
+
|
571
|
+
# 3 创建临时脚本文件
|
572
|
+
script_file = XlPath.create_tempfile_path(extension)
|
573
|
+
script_file.write_text(script_content)
|
574
|
+
|
575
|
+
# 4 根据文件扩展名和操作系统选择执行命令
|
576
|
+
if extension == '.sh':
|
577
|
+
cmd = ['bash', str(script_file)]
|
578
|
+
elif extension == '.ps1':
|
579
|
+
if sys.platform == 'win32':
|
580
|
+
cmd = ['powershell', '-ExecutionPolicy', 'Bypass', '-File', str(script_file)]
|
581
|
+
else:
|
582
|
+
raise ValueError("PowerShell 脚本仅在 Windows 系统上受支持")
|
583
|
+
elif extension == '.bat':
|
584
|
+
cmd = [str(script_file)] # 直接运行 .bat 文件
|
585
|
+
else:
|
586
|
+
raise ValueError(f"不支持的脚本类型: {extension}")
|
587
|
+
|
588
|
+
# 5 使用 add_program_cmd3 启动脚本
|
589
|
+
return self.add_program_cmd3(
|
590
|
+
cmd=cmd,
|
591
|
+
name=name or f"command_{script_file.stem}",
|
592
|
+
shell=shell,
|
593
|
+
run=run,
|
594
|
+
schedule=schedule,
|
595
|
+
**kwargs
|
596
|
+
)
|
597
|
+
|
598
|
+
def __3_nginx相关(self):
|
599
|
+
pass
|
600
|
+
|
601
|
+
def get_all_locations(self):
|
602
|
+
locations = defaultdict(list)
|
603
|
+
for worker in self.workers:
|
604
|
+
if not worker.locations:
|
605
|
+
continue
|
606
|
+
for x in worker.locations:
|
607
|
+
for dst, src in x.items():
|
608
|
+
locations[dst].append(f'localhost:{worker.port}{src}')
|
609
|
+
return locations
|
610
|
+
|
611
|
+
def configure_nginx(self, nginx_template, locations=None):
|
612
|
+
if locations is None:
|
613
|
+
locations = self.get_all_locations()
|
614
|
+
|
615
|
+
upstreams = [] # 外部的配置
|
616
|
+
servers = [nginx_template.rstrip()] # 内部的配置
|
617
|
+
|
618
|
+
for dst, srcs in locations.items():
|
619
|
+
if len(srcs) == 1: # 只有1个不开负载
|
620
|
+
server = f'location {dst} {{\n\tproxy_pass http://{srcs[0]};\n}}\n'
|
621
|
+
else: # 有多个端口功能则开负载
|
622
|
+
hosts = '\n'.join([f'\tserver {src.split("/")[0]};' for src in srcs])
|
623
|
+
upstream_name = 'upstream' + str(len(upstreams) + 1)
|
624
|
+
upstreams.append(f'upstream {upstream_name} {{\n{hosts}\n}}\n')
|
625
|
+
sub_urls = [src.split('/', maxsplit=1)[1] for src in srcs]
|
626
|
+
assert len(set(sub_urls)) == 1, f'负载均衡的子url必须一致 {sub_urls}'
|
627
|
+
server = f'location {dst} {{\n\tproxy_pass http://{upstream_name}/{sub_urls[0]};\n}}\n'
|
628
|
+
servers.append(server)
|
629
|
+
|
630
|
+
content = '\n'.join(upstreams) + '\nserver {\n' + textwrap.indent('\n'.join(servers), '\t') + '}'
|
631
|
+
return content
|
632
|
+
|
633
|
+
def __4_多程序管理(self):
|
493
634
|
pass
|
494
635
|
|
636
|
+
def count_running(self):
|
637
|
+
return sum(1 for worker in self.workers if worker.is_running())
|
638
|
+
|
639
|
+
def list_workers(self):
|
640
|
+
"""返回所有任务的状态 DataFrame"""
|
641
|
+
ls = []
|
642
|
+
for worker in self.workers:
|
643
|
+
ls.append({
|
644
|
+
'name': worker.name,
|
645
|
+
'pid': worker.program.pid if worker.program else None,
|
646
|
+
'poll': worker.program.poll() if worker.program else None,
|
647
|
+
'args': worker.raw_cmd,
|
648
|
+
'port': worker.port,
|
649
|
+
'locations': worker.locations,
|
650
|
+
})
|
651
|
+
return pd.DataFrame(ls)
|
652
|
+
|
495
653
|
def cleanup_finished(self, exit_code=None):
|
496
654
|
"""
|
497
655
|
清除已运行完的程序
|
@@ -522,47 +680,51 @@ class MultiProgramLauncher:
|
|
522
680
|
worker.terminate()
|
523
681
|
self.workers = []
|
524
682
|
|
525
|
-
def
|
683
|
+
def proc_cmd(self, cmd):
|
684
|
+
if cmd == 'kill':
|
685
|
+
self.stop_all()
|
686
|
+
return False
|
687
|
+
elif cmd == 'count':
|
688
|
+
print(f'有{self.count_running()}个程序正在运行')
|
689
|
+
elif cmd.startswith('cleanup'):
|
690
|
+
args = cmd.split()
|
691
|
+
exit_code = int(args[1]) if len(args) > 1 else None
|
692
|
+
self.cleanup_finished(exit_code)
|
693
|
+
print("清理完成")
|
694
|
+
elif cmd == 'list': # 列出所有程序(转df查看)
|
695
|
+
df = self.list_workers()
|
696
|
+
print_full_dataframe(df)
|
697
|
+
return True
|
698
|
+
|
699
|
+
def run_endless(self, cmd=True, wait_seconds=1, *, port=None):
|
526
700
|
"""
|
527
701
|
一直运行,直到用户输入 kill 命令或 Ctrl+C
|
528
702
|
|
529
|
-
|
703
|
+
:param bool cmd: 是否支持命令行input输入指令监控状态的模式
|
704
|
+
默认支持,但在有scheduler调度的情况不建议开启,有input阻塞其他子程的风险
|
705
|
+
:param int|float wait_seconds: 每次循环之间停顿秒数,用来给其他子程等运行时间,避免阻塞
|
706
|
+
:param int port: 是否要开一个后端服务,支持查询程序运行状态
|
707
|
+
|
708
|
+
poll:
|
530
709
|
如果进程仍在运行,poll()方法返回None。
|
531
710
|
如果进程已经结束,poll()方法返回进程的退出码(exit code)。
|
532
711
|
如果进程正常结束,退出码通常为0。
|
533
712
|
如果进程异常结束,退出码通常是一个非零值,表示异常的类型或错误码。
|
534
|
-
|
535
|
-
import pandas as pd
|
536
|
-
from pyxllib.algo.stat import print_full_dataframe
|
537
|
-
|
713
|
+
"""
|
538
714
|
if self.scheduler: # 如果有定时任务,启动调度器
|
539
715
|
self.scheduler.start()
|
540
716
|
|
717
|
+
if port:
|
718
|
+
dashboard = LauncherDashboard(self)
|
719
|
+
threading.Thread(target=lambda: dashboard.run(port), daemon=True).start()
|
720
|
+
|
541
721
|
try:
|
542
722
|
while True:
|
543
|
-
cmd
|
544
|
-
|
545
|
-
self.
|
546
|
-
|
547
|
-
|
548
|
-
# 需要实际检查现有程序
|
549
|
-
m = sum([1 for worker in self.workers if worker.is_running()])
|
550
|
-
print(f'有{m}个程序正在运行')
|
551
|
-
elif cmd.startswith('cleanup'):
|
552
|
-
# 获取 exit_code 参数
|
553
|
-
args = cmd.split()
|
554
|
-
if len(args) > 1: # 支持跟一个参数,删除制定状态的程序
|
555
|
-
exit_code = int(args[1])
|
556
|
-
else:
|
557
|
-
exit_code = None
|
558
|
-
self.cleanup_finished(exit_code)
|
559
|
-
print("清理完成")
|
560
|
-
elif cmd == 'list': # 列出所有程序(转df查看)
|
561
|
-
ls = []
|
562
|
-
for worker in self.workers:
|
563
|
-
ls.append([worker.name, worker.program.pid, worker.program.poll(), worker.raw_cmd])
|
564
|
-
df = pd.DataFrame(ls, columns=['name', 'pid', 'poll', 'args'])
|
565
|
-
print_full_dataframe(df)
|
723
|
+
if cmd:
|
724
|
+
_cmd = input(">>> ")
|
725
|
+
if not self.proc_cmd(_cmd):
|
726
|
+
break
|
727
|
+
time.sleep(wait_seconds)
|
566
728
|
except KeyboardInterrupt:
|
567
729
|
print("\n检测到 Ctrl+C,正在终止所有程序...")
|
568
730
|
self.stop_all()
|
@@ -579,6 +741,78 @@ class MultiProcessLauncher(MultiProgramLauncher):
|
|
579
741
|
pass
|
580
742
|
|
581
743
|
|
744
|
+
class LauncherDashboard:
|
745
|
+
def __init__(self, launcher):
|
746
|
+
self.launcher = launcher
|
747
|
+
self.app = FastAPI()
|
748
|
+
self.setup_routes()
|
749
|
+
|
750
|
+
def setup_routes(self):
|
751
|
+
@self.app.get("/", response_class=PlainTextResponse)
|
752
|
+
async def home():
|
753
|
+
"""主页,展示所有任务状态"""
|
754
|
+
df = self.launcher.list_workers()
|
755
|
+
return self.render_text(df)
|
756
|
+
|
757
|
+
@self.app.get("/count", response_class=PlainTextResponse)
|
758
|
+
async def get_count():
|
759
|
+
"""返回正在运行的任务数量"""
|
760
|
+
count = self.launcher.count_running()
|
761
|
+
return f"正在运行的任务数量: {count}\n"
|
762
|
+
|
763
|
+
@self.app.post("/stop", response_class=PlainTextResponse)
|
764
|
+
async def stop_all():
|
765
|
+
"""停止所有任务"""
|
766
|
+
self.launcher.stop_all()
|
767
|
+
return "所有任务已停止。\n"
|
768
|
+
|
769
|
+
@self.app.post("/cleanup", response_class=PlainTextResponse)
|
770
|
+
async def cleanup(exit_code: int = None):
|
771
|
+
"""清理已完成的任务"""
|
772
|
+
self.launcher.cleanup_finished(exit_code)
|
773
|
+
return "清理完成。\n"
|
774
|
+
|
775
|
+
def render_text(self, df):
|
776
|
+
"""生成纯文本格式的任务状态"""
|
777
|
+
if df.empty:
|
778
|
+
return "没有任务正在运行。\n"
|
779
|
+
|
780
|
+
# 调整表头以显示新的属性:port 和 locations
|
781
|
+
output = ["当前任务状态:\n"]
|
782
|
+
output.append(f"{'编号':<5} {'名称':<15} {'PID':<10} {'状态':<10} {'端口':<10} {'位置':<20} {'命令'}")
|
783
|
+
output.append("-" * 120)
|
784
|
+
|
785
|
+
for idx, (_, row) in enumerate(df.iterrows(), start=1):
|
786
|
+
name = row['name']
|
787
|
+
|
788
|
+
# 更鲁棒地处理 pid,考虑 NaN 情况
|
789
|
+
pid = "N/A" if pd.isna(row['pid']) else int(row['pid'])
|
790
|
+
|
791
|
+
# 获取任务状态
|
792
|
+
status = "运行中" if row['poll'] is None else "已结束"
|
793
|
+
|
794
|
+
# 处理 args,确保路径展示更清晰
|
795
|
+
args = [a for a in row['args'] if a] if isinstance(row['args'], list) else []
|
796
|
+
args_str = "[" + ", ".join(
|
797
|
+
repr(arg).replace("\\\\", "\\") if '\\' in arg else repr(arg) for arg in args
|
798
|
+
) + "]"
|
799
|
+
|
800
|
+
# 处理 port 和 locations
|
801
|
+
port = row['port'] if not pd.isna(row['port']) else "N/A"
|
802
|
+
locations = ", ".join(row['locations']) if isinstance(row['locations'], list) else "N/A"
|
803
|
+
|
804
|
+
# 格式化输出
|
805
|
+
output.append(f"{idx:<5} {name:<15} {pid:<10} {status:<10} {port:<10} {locations:<20} {args_str}")
|
806
|
+
|
807
|
+
output.append("\n")
|
808
|
+
return "\n".join(output)
|
809
|
+
|
810
|
+
def run(self, port=8080):
|
811
|
+
"""启动 FastAPI 服务"""
|
812
|
+
import uvicorn
|
813
|
+
uvicorn.run(self.app, host="0.0.0.0", port=port, log_level="warning")
|
814
|
+
|
815
|
+
|
582
816
|
def __3_装饰器工具():
|
583
817
|
pass
|
584
818
|
|