{"id":15550061,"url":"https://github.com/hscspring/pnlp","last_synced_at":"2025-09-27T03:31:52.799Z","repository":{"id":57307064,"uuid":"182029830","full_name":"hscspring/pnlp","owner":"hscspring","description":"NLP预/后处理工具。","archived":false,"fork":false,"pushed_at":"2024-07-18T02:53:07.000Z","size":95,"stargazers_count":29,"open_issues_count":0,"forks_count":6,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-01-10T14:15:49.849Z","etag":null,"topics":["chinese-nlp","concurrency","nlp","nlp-enhancer","nlp-preprocess","normalization","preprocessing","text-cleaning","text-extraction","text-length","text-processing"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hscspring.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2019-04-18T06:32:48.000Z","updated_at":"2024-08-15T12:08:23.000Z","dependencies_parsed_at":"2023-01-30T21:30:44.004Z","dependency_job_id":"2de2392b-e3a7-4471-bd28-cbb448237548","html_url":"https://github.com/hscspring/pnlp","commit_stats":{"total_commits":60,"total_committers":2,"mean_commits":30.0,"dds":"0.033333333333333326","last_synced_commit":"2c867d1b67cacc044f779586f151cfbe9a65b1d6"},"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hscspring%2Fpnlp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hscspring%2Fpnlp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hscspring%2Fpnlp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hscspring%2Fpnlp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hscspring","download_url":"https://codeload.github.com/hscspring/pnlp/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":234382669,"owners_count":18823332,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["chinese-nlp","concurrency","nlp","nlp-enhancer","nlp-preprocess","normalization","preprocessing","text-cleaning","text-extraction","text-length","text-processing"],"created_at":"2024-10-02T13:49:26.792Z","updated_at":"2025-09-27T03:31:47.383Z","avatar_url":"https://github.com/hscspring.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003c!-- START doctoc generated TOC please keep comment here to allow auto update --\u003e\n\u003c!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE --\u003e\n**Table of Contents**  *generated with [DocToc](https://github.com/thlorenz/doctoc)*\n\n- [功能特性](#%E5%8A%9F%E8%83%BD%E7%89%B9%E6%80%A7)\n- [安装](#%E5%AE%89%E8%A3%85)\n- [使用](#%E4%BD%BF%E7%94%A8)\n  - [文本IO](#%E6%96%87%E6%9C%ACio)\n    - [IO 处理](#io-%E5%A4%84%E7%90%86)\n    - [内置方法](#%E5%86%85%E7%BD%AE%E6%96%B9%E6%B3%95)\n  - [文本处理](#%E6%96%87%E6%9C%AC%E5%A4%84%E7%90%86)\n    - [清理和提取](#%E6%B8%85%E7%90%86%E5%92%8C%E6%8F%90%E5%8F%96)\n    - [内置正则](#%E5%86%85%E7%BD%AE%E6%AD%A3%E5%88%99)\n  - [文本切分](#%E6%96%87%E6%9C%AC%E5%88%87%E5%88%86)\n    - [任意部分切分](#%E4%BB%BB%E6%84%8F%E9%83%A8%E5%88%86%E5%88%87%E5%88%86)\n    - [分句](#%E5%88%86%E5%8F%A5)\n    - [分子句并按一个阈值合并子句](#%E5%88%86%E5%AD%90%E5%8F%A5%E5%B9%B6%E6%8C%89%E4%B8%80%E4%B8%AA%E9%98%88%E5%80%BC%E5%90%88%E5%B9%B6%E5%AD%90%E5%8F%A5)\n    - [中文字符切分](#%E4%B8%AD%E6%96%87%E5%AD%97%E7%AC%A6%E5%88%87%E5%88%86)\n    - [句子分组](#%E5%8F%A5%E5%AD%90%E5%88%86%E7%BB%84)\n  - [文本增强](#%E6%96%87%E6%9C%AC%E5%A2%9E%E5%BC%BA)\n    - [Token级别](#token%E7%BA%A7%E5%88%AB)\n    - [句子级别](#%E5%8F%A5%E5%AD%90%E7%BA%A7%E5%88%AB)\n  - [文本归一化](#%E6%96%87%E6%9C%AC%E5%BD%92%E4%B8%80%E5%8C%96)\n    - [中文数字](#%E4%B8%AD%E6%96%87%E6%95%B0%E5%AD%97)\n  - [格式转换](#%E6%A0%BC%E5%BC%8F%E8%BD%AC%E6%8D%A2)\n    - [BIO转实体](#bio%E8%BD%AC%E5%AE%9E%E4%BD%93)\n    - [任意参数转UUID](#%E4%BB%BB%E6%84%8F%E5%8F%82%E6%95%B0%E8%BD%ACuuid)\n  - [内置词典](#%E5%86%85%E7%BD%AE%E8%AF%8D%E5%85%B8)\n    - [停用词](#%E5%81%9C%E7%94%A8%E8%AF%8D)\n  - [文本长度](#%E6%96%87%E6%9C%AC%E9%95%BF%E5%BA%A6)\n  - [魔术方法](#%E9%AD%94%E6%9C%AF%E6%96%B9%E6%B3%95)\n  - [并行处理](#%E5%B9%B6%E8%A1%8C%E5%A4%84%E7%90%86)\n- [测试](#%E6%B5%8B%E8%AF%95)\n- [更新日志](#%E6%9B%B4%E6%96%B0%E6%97%A5%E5%BF%97)\n\n\u003c!-- END doctoc generated TOC please keep comment here to allow auto update --\u003e\n\nNLP 预/后处理工具。\n\n## 功能特性\n\n- 专为文本 IO 设计的灵活的 Pipeline\n- 灵活的文本清理/提取工具\n- 文本增强\n- 按句切分或按中文字符切分文本\n- 文本分桶\n- 中文字符归一化\n- 文本各种长度计算\n- 中英文常用停用词\n- 预处理魔术方法\n- 并发、批量化、实体 BIO 转实体\n\n## 安装\n\n需要 Python3.7+。\n\n`pip install pnlp`\n\n## 使用\n\n### 文本IO\n\n#### IO 处理\n\n```bash\ntree tests/piop_data/\n├── a.md\n├── b.txt\n├── c.data\n├── first\n│   ├── fa.md\n│   ├── fb.txt\n│   ├── fc.data\n│   └── second\n│       ├── sa.md\n│       ├── sb.txt\n│       └── sc.data\n├── json.json\n├── outfile.file\n├── outjson.json\n└── yml.yml\n```\n\n```python\nimport os\nfrom pnlp import Reader\n\nDATA_PATH = \"./pnlp/tests/piop_data/\"\npattern = '*.md' # 可以是 '*.txt', 'f*.*' 等，支持正则\nreader = Reader(pattern, use_regex=True)\n\n# 获取所有文件的行，输出行文本、行索引和所在的文件名\nfor line in reader(DATA_FOLDER_PATH):\n    print(line.lid, line.fname, line.text)\n\"\"\"\n0 a.md line 1 in a.\n1 a.md line 2 in a.\n2 a.md line 3 in a.\n0 fa.md line 1 in fa.\n1 fa.md line 2 in fa\n...\n\"\"\"\n\n# 获取某个文件的所有行，输出行文本、行索引和所在文件名，此时由于指定了文件名 pattern 无效\nfor line in reader(os.path.join(DATA_FOLDER_PATH, \"a.md\")):\n    print(line.lid, line.fname, line.text)\n\"\"\"\n0 a.md line 1 in a.\n1 a.md line 2 in a.\n2 a.md line 3 in a.\n\"\"\"\n\n\n\n# 获取目录下的所有文件路径\nfor path in Reader.gen_files(DATA_PATH, pattern, use_regex: True):\n    print(path)\n\"\"\"\npnlp/tests/piop_data/a.md\npnlp/tests/piop_data/first/fa.md\npnlp/tests/piop_data/first/second/sa.md\n\"\"\"\n\n# 获取一个目录下所有文件名和它们的内容\npaths = Reader.gen_files(DATA_PATH, pattern)\narticles = Reader.gen_articles(paths)\nfor article in articles:\n    print(article.fname)\n    print(article.f.read())\n\"\"\"\na.md\nline 1 in a.\nline 2 in a.\nline 3 in a.\n...\n\"\"\"\n\n# 同前两个例子\npaths = Reader.gen_files(DATA_PATH, pattern)\narticles = Reader.gen_articles(paths)\nfor line in Reader.gen_flines(articles, strip=\"\\n\"):\n    print(line.lid, line.fname, line.text)\n```\n\n#### 内置方法\n\n```python\nimport pnlp\n\n# Read\nfile_string = pnlp.read_file(file_path)\nfile_list = pnlp.read_lines(file_path)\nfile_json = pnlp.read_json(file_path)\nfile_yaml = pnlp.read_yaml(file_path)\nfile_csv = pnlp.read_csv(file_path)\nfile_pickle = pnlp.read_pickle(file_path)\nlist_dict = pnlp.read_file_to_list_dict(file_path)\n\n# Write\npnlp.write_json(file_path, data, indent=2)\npnlp.write_file(file_path, data)\npnlp.write_pickle(file_path, data)\npnlp.write_list_dict_to_file(file_path, data)\n\n# Others\npnlp.check_dir(dirname) # 如果目录不存在会创建\n```\n\n### 文本处理\n\n#### 清理和提取\n\n```python\nimport re\nfrom pnlp import Text\n\ntext = \"这是https://www.yam.gift长度测试，《 》*)FSJfdsjf😁![](http://xx.jpg)。233.\"\npattern = re.compile(r'\\d+')\n\n# pattern 是 re.Pattern 类型或 str 类型\n# 默认为空字符串：'', 表示不使用任何 pattern（实际是 re.compile(r'.+')），此时 clean 返回空（全部被清了），extract 返回原始文本。\n# pattern 支持以下字符串类型（实际为正则）：\n#\t'chi': 中文字符\n#\t'pun': 标点\n#\t'whi': 空白\n#\t'nwh': 非空白\n#\t'wnb': 字母（含中文字符）或数字\n#\t'nwn': 非字母（含中文字符）或数字\n#\t'eng': 英文字符\n#\t'num': 数字\n#\t'pic': 图片\n#\t'lnk': 链接\n#\t'emj': 表情\n\npt = Text(['chi', pattern])\n\n# 提取所有符合 pattern 的文本和它们的位置\nres = pt.extract(text)\nprint(res)\n\"\"\"\n{'text': '这是长度测试233', 'mats': ['这是', '长度测试', '233'], 'locs': [(0, 2), (22, 26), (60, 63)]}\n\"\"\"\n# 支持用「点」获取key属性\nprint(res.text, res.mats, res.locs)\n\"\"\"\n'这是长度测试' ['这是', '长度测试'] [(0, 2), (22, 26)]\n\"\"\"\n\n# 返回指定 pattern 清理后的文本\nprint(pt.clean(text))\n\"\"\"\nhttps://www.yam.gift，《 》*)FSJfdsjf😁![](http://xx.jpg)。233.\n\"\"\"\n\n# 可以指定多个 pattern，注意先后顺序可能会影响结果哦\npt = Text(['pic', 'lnk'])\n# 提取到的\nres = pt.extract(text)\nprint(res.mats)\n\"\"\"\n['https://www.yam.gif',\n '![](http://xx.jpg)',\n 'https://www.yam.gift',\n 'http://xx.jpg']\n\"\"\"\n# 清理后的\nprint(pt.clean(text))\n\"\"\"\n这是t长度测试，《 》*)FSJfdsjf😁。233.\n\"\"\"\n```\n\n#### 内置正则\n\n```python\n# USE Regex\nfrom pnlp import reg\ndef clean_text(text: str) -\u003e str:\n    text = reg.pwhi.sub(\"\", text)\n    text = reg.pemj.sub(\"\", text)\n    text = reg.ppic.sub(\"\", text)\n    text = reg.plnk.sub(\"\", text)\n    return text\n```\n\n### 文本切分\n\n#### 任意部分切分\n\n```python\n# Cut by Regex\nfrom pnlp import cut_part, psent\ntext = \"你好！欢迎使用。\"\nsent_list = cut_part(text, psent, with_spliter=True, with_offset=False)\nprint(sent_list)\n\"\"\"\n['你好！', '欢迎使用。']\n\"\"\"\npcustom_sent = re.compile(r'[。！]')\nsent_list = cut_part(text, pcustom_sent, with_spliter=False, with_offset=False)\nprint(sent_list)\n\"\"\"\n['你好', '欢迎使用']\n\"\"\"\nsent_list = cut_part(text, pcustom_sent, with_spliter=False, with_offset=True)\nprint(sent_list)\n\"\"\"\n[('你好', 0, 3), ('欢迎使用', 3, 8)]\n\"\"\"\n```\n\n#### 分句\n\n```python\n# Cut Sentence\nfrom pnlp import cut_sentence as pcs\ntext = \"你好！欢迎使用。\"\nsent_list = pcs(text)\nprint(sent_list)\n\"\"\"\n['你好！', '欢迎使用。']\n\"\"\"\n```\n\n#### 分子句并按一个阈值合并子句\n\n```python\nfrom pnlp import cut_sub_sentence as pcss\ntext = \"你好！你好。你好？你坏~欢迎使用。\"\nsent_list = pcss(text)\nprint(sent_list)\n\"\"\"\n['你好！', '你好。', '你好？', '你坏~', '欢迎使用。']\n\"\"\"\nsent_list = pcss(text, 6)\nprint(sent_list)\n\"\"\"\n['你好！你好。', '你好？你坏~', '欢迎使用。']\n\"\"\"\nsent_list = pcss(text, 12)\nprint(sent_list)\n\"\"\"\n['你好！你好。你好？你坏~', '欢迎使用。']\n\"\"\"\n```\n\n这个功能在很多场合非常有用；）懂的都懂：D\n\n#### 中文字符切分\n\n```python\n# 中文字符切分\nfrom pnlp import cut_zhchar\ntext = \"你好，hello, 520 i love u. = ”我爱你“。\"\nchar_list = cut_zhchar(text)\nprint(char_list)\n\"\"\"\n['你', '好', '，', 'hello', ',', ' ', '520', ' ', 'i', ' ', 'love', ' ', 'u', '.', ' ', '=', ' ', '”', '我', '爱', '你', '“', '。']\n\"\"\"\nchar_list = cut_zhchar(text, remove_blank=True)\nprint(char_list)\n\"\"\"\n['你', '好', '，', 'hello', ',', '520', 'i', 'love', 'u', '.', '=', '”', '我', '爱', '你', '“', '。']\n\"\"\"\n```\n\n#### 句子分组\n\n```python\nfrom pnlp import combine_bucket\nparts = [\n    \"先生，那夜，我因胸中纳闷，无法入睡，\",\n    \"折腾得比那铐了脚镣的叛变水手还更难过；\",\n    \"那时，我就冲动的 ——\",\n    \"好在有那一时之念，\",\n    \"因为有时我们在无意中所做的事能够圆满……\"\n]\nbuckets = combine_bucket(parts.copy(), 10, truncate=True, keep_remain=True)\nprint(buckets)\n\"\"\"\n['先生，那夜，我因胸中',\n '纳闷，无法入睡，',\n '折腾得比那铐了脚镣的',\n '叛变水手还更难过；',\n '那时，我就冲动的 —',\n '—',\n '好在有那一时之念，',\n '因为有时我们在无意中',\n '所做的事能够圆满……']\n\"\"\"\n```\n\n### 文本增强\n\n采样器支持删除、交换、插入操作，所有的操作不会跨越标点。\n\n#### Token级别\n\n- 默认 Tokenizer\n    - 中文：字符级 Tokenizer（见上）\n    - 英文：空白符切分 Tokenizer\n- Tokenizer 可以任意指定，但它的输出应该是一个 List 的 Token 或一个 List 的 Tuple，每个 Tuple 包含一个 Token 和一个词性。\n- 对字符级增强，默认并不会操作所有字或词。可以自定义要操作的词或词性。\n    - 默认 Token 是「停用词」\n    - 默认词性（当 Tokenizer 输出带词性时）是「功能词」：副词、介词、连词、助词、其他虚词（标记为 d p c u xc）\n\n```python\n# 【】内的为改变的\ntext = \"人为什么活着？生而为人必须要有梦想！还要有尽可能多的精神体验。\"\n# 字符粒度\nfrom pnlp import TokenLevelSampler\ntls = TokenLevelSampler()\ntls.make_samples(text)\n\"\"\"\n{'delete': '人为什么活着？生而为人必须要【有】梦想！还要有尽可能多的精神体验。',\n 'swap': '【为】【人】什么活着？生而为人必须要有梦想！还要有尽可能多的精神体验。',\n 'insert': '人为什么活着？生而为人必须要有梦想！【还】还要有尽可能多的精神体验。',\n 'together': '人什么着着活？生而必为为须要有梦想！还要有尽可能多的精神体验。'}\n\"\"\"\n# 支持自定义 tokenizer\ntls.make_samples(text, jieba.lcut)\n\"\"\"\n{'delete': '人为什么活着？生而为人【必须】要有梦想！还要有尽可能多的精神体验。',\n 'swap': '【为什么】【人】活着？生而为人必须要有梦想！还要有尽可能多的精神体验。',\n 'insert': '人为什么活着？生而为人必须要有梦想！【还要】还要有尽可能多的精神体验。',\n 'together': '人为什么活着？生而为人人要有梦想！还要有多尽可能的精神体验。'}\n\"\"\"\n# 自定义\ntls = TokenLevelSampler(\n    rate=替换比例, # 默认 5%\n    types=[\"delete\", \"swap\", \"insert\"], # 默认三个 \n    sample_words=[\"词1\", \"词2\"], # 默认停用词\n    sample_pos=[\"词性1\", \"词性2\"], # 默认功能词\n)\n```\n\n#### 句子级别\n\n```python\nfrom pnlp import SentenceLevelSampler\nsls = SentenceLevelSampler()\nsls.make_samples(text)\n\"\"\"\n{'delete': '生而为人必须要有梦想！还要有尽可能多的精神体验。',\n 'swap': '人为什么活着？还要有尽可能多的精神体验。生而为人必须要有梦想！',\n 'insert': '人为什么活着？还要有尽可能多的精神体验。生而为人必须要有梦想！生而为人必须要有梦想！',\n 'together': '生而为人必须要有梦想！人为什么活着？人为什么活着？'}\n\"\"\"\n# 自定义\nsls = SentenceLevelSampler(types=[\"delete\", \"swap\", \"insert\"]) # 默认三个\n```\n\n### 文本归一化\n\n#### 中文数字\n\n```python\nfrom pnlp import num_norm\nnum_norm.num2zh(1024) == \"一千零二十四\"\nnum_norm.num2zh(1024).to_money() == \"壹仟零贰拾肆\"\nnum_norm.zh2num(\"一千零二十四\") == 1024\n```\n\n### 格式转换\n\n#### BIO转实体\n\n```python\n# 实体 BIO Token 转实体\nfrom pnlp import pick_entity_from_bio_labels\npairs = [('天', 'B-LOC'), ('安', 'I-LOC'), ('门', 'I-LOC'), ('有', 'O'), ('毛', 'B-PER'), ('主', 'I-PER'), ('席', 'I-PER')]\npick_entity_from_bio_labels(pairs)\n\"\"\"\n[('天安门', 'LOC'), ('毛主席', 'PER')]\n\"\"\"\npick_entity_from_bio_labels(pairs, with_offset=True)\n\"\"\"\n[('天安门', 'LOC', 0, 3), ('毛主席', 'PER', 4, 7)]\n\"\"\"\n```\n\n#### 任意参数转UUID\n\n```python\nfrom pnlp import generate_uuid\n\nuid1 = pnlp.generate_uuid(\"a\", 1, 0.02)\nuid2 = pnlp.generete_uuid(\"a\", 1)\n\"\"\"\nuid1 == 3fbc8b70d05b5abdb5badca1d26e1dbd\nuid2 == f7b0ffc589e453e88d4faf66eb92f669\n\"\"\"\n```\n\n### 内置词典\n\n#### 停用词\n\n```python\nfrom pnlp import StopWords, chinese_stopwords, english_stopwords\n\ncsw = StopWords(\"/path/to/custom/stopwords.txt\")\ncsw.stopwords # a set of the custom stopwords\n\ncsw.zh == chinese_stopwords # Chineses stopwords\ncsw.en == english_stopwords # English stopwords\n```\n\n\n### 文本长度\n\n```python\nfrom pnlp import Length\n\ntext = \"这是https://www.yam.gift长度测试，《 》*)FSJfdsjf😁![](http://xx.jpg)。233.\"\n\npl = Length(text)\n# 注意：即使使用了 pattern，长度都是基于原始文本\n# 长度基于字符计数（不是整词）\nprint(\"Length of all characters: \", pl.len_all)\nprint(\"Length of all non-white characters: \", pl.len_nwh)\nprint(\"Length of all Chinese characters: \", pl.len_chi)\nprint(\"Length of all words and numbers: \", pl.len_wnb)\nprint(\"Length of all punctuations: \", pl.len_pun)\nprint(\"Length of all English characters: \", pl.len_eng)\nprint(\"Length of all numbers: \", pl.len_num)\n\n\"\"\"\nLength of all characters:  64\nLength of all non-white characters:  63\nLength of all Chinese characters:  6\nLength of all words and numbers:  41\nLength of all punctuations:  14\nLength of all English characters:  32\nLength of all numbers:  3\n\"\"\"\n```\n\n### 魔术方法\n\n#### 字典\n\n```python\nfrom pnlp import MagicDict\n\n# 嵌套字典\npmd = MagicDict()\npmd['a']['b']['c'] = 2\nprint(pmd)\n\n\"\"\"\n{'a': {'b': {'c': 2}}}\n\"\"\"\n\n# 当字典被翻转时，保留所有的重复 value-keys\ndx = {1: 'a',\n      2: 'a',\n      3: 'a',\n      4: 'b' }\nprint(pmag.MagicDict.reverse(dx))\n\n\"\"\"\n{'a': [1, 2, 3], 'b': 4}\n\"\"\"\n```\n\n#### 获取唯一文件名\n\n```python\nfrom pnlp import get_unique_fn\n\nget_unique_fn(\"a/b/c.md\") == \"a_b_c.md\"\n```\n\n### 并行处理\n\n支持四种并行处理方式：\n\n- 线程池：`thread_pool`\n- 进程池：`process_pool`\n- 线程 Executor：`thread_executor`，默认使用\n- 线程：`thread`\n\n注意：惰性处理，返回的是 Generator。\n\n```python\nimport math\ndef is_prime(x):\n    if x \u003c 2:\n        return False\n    for i in range(2, int(math.sqrt(x)) + 1):\n        if x % i == 0:\n            return False\n    return True\n\nfrom pnlp import concurring\n\n# max_workers 默认为 4\n@concurring\ndef get_primes(lst):\n    res = []\n    for i in lst:\n        if is_prime(i):\n            res.append(i)\n    return res\n\n@concurrint(type=\"thread_pool\", max_workers=10)\ndef get_primes(lst):\n    pass\n```\n\n`concurring` 装饰器让你的迭代函数并行。\n\n### 后台处理\n\n```python\nfrom pnlp import run_in_new_thread\n\ndef func(file, a, b, c):\n    background_task()\n\nrun_in_new_thread(func, file, 1, 2, 3)\n```\n\n## 测试\n\nClone 仓库后执行：\n\n```bash\n$ python -m pytest\n```\n\n## 更新日志\n\n见英文版 README。\n\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhscspring%2Fpnlp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhscspring%2Fpnlp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhscspring%2Fpnlp/lists"}