def modify_file(file, func, *, outfile=None, file_mode=None, debug=0): """ 对单个文件就行优化的功能函数 这样一些底层函数功能可以写成数据级的接口,然后由这个函数负责文件的读写操作,并且支持debug比较前后内容差异 :param outfile: 默认是对file原地操作,如果使用该参数,则将处理后的内容写入outfile文件 :param file_mode: 指定文件读取类型格式,例如'.json'是json文件,读取为字典 :param debug: 这个功能可以对照refine分级轮理解 无outfile参数时,原地操作 0,【直接原地操作】关闭调试,直接运行 (根据outfile=None选择原地操作,或者指定生成新文件) 1,【进行审核】打开BC比较差异,左边原始内容,右边参考内容 (打开前后差异内容对比) -1,【先斩后奏】介于完全不调试和全部人工检查之间,特殊的差异比较。左边放原始文件修改后的结果,右边对照原内容。 有outfile参数时 0 | False,直接生成目标文件,如果outfile已存在会被覆盖 1 | True,直接生成目标文件,但是会弹出bc比较前后内容差异 (相同内容不会弹出) """ infile = File(file) enc = get_encoding(infile.read(mode='b')) data = infile.read(mode=file_mode, encoding=enc) origin_content = str(data) new_data = func(data) isdiff = origin_content != str(new_data) if outfile is None: # 原地操作 if isdiff: # 内容不同才会有相关debug功能,否则静默跳过就好 if debug == 0: infile.write(new_data, mode=file_mode) # 直接处理 elif debug == 1: temp_file = File('refine_content', Dir.TEMP, suffix=infile.suffix).write(new_data) bcompare(infile, temp_file) # 使用beyond compare软件打开对比查看 elif debug == -1: temp_file = File('origin_content', Dir.TEMP, suffix=infile.suffix) infile.copy(temp_file) infile.write(new_data, mode=file_mode, encoding=enc) # 把原文件内容替换了 bcompare(infile, temp_file) # 然后显示与旧内容进行对比 else: raise ValueError(f'{debug}') else: outfile = File(outfile) outfile.write(new_data, mode=file_mode, encoding=enc) # 直接处理 if debug and isdiff: bcompare(infile, outfile) return isdiff
def from_file(cls, file, **kwargs): """ 输入本地一个html文件的路径,加上导航栏打开 """ file = File(file) content = file.read() # 输入文件的情况,生成的_content等html要在同目录 return cls.from_content(content, os.path.splitext(str(file))[0], **kwargs)
def distribute_package(root, version=None, repository=None, *, upload=True): """ 发布包的工具函数 :param root: 项目的根目录,例如 'D:/slns/pyxllib' 根目录下有对应的 setup.py 等文件 :param repository: 比如我配置了 [xlpr],就可以传入 'xlpr' """ from pyxllib.file.specialist import File, Dir # 1 切换工作目录 os.chdir(str(root)) # 2 改版本号 if version: f = File('setup.py', root) s = re.sub(r"(version\s*=\s*)(['\"])(.+?)(\2)", fr'\1\g<2>{version}\4', f.read()) f.write(s) # 3 打包 subprocess.run('python setup.py sdist') # 4 上传 if upload: # 上传 cmd = 'twine upload dist/*' if repository: cmd += f' -r {repository}' subprocess.run(cmd) # 删除打包生成的中间文件 Dir('dist').delete() Dir('build').delete()
def __init__(self, root, relpath2data=None, *, reads=True, prt=False, fltr=None, slt=None, extdata=None): """ :param root: 数据所在根目录 :param dict[str, readed_data] relpath2data: {relpath: data1, 'a/1.txt': data2, ...} 如果未传入data具体值,则根据目录里的情况自动初始化获得data的值 relpath是对应的File标注文件的相对路径字符串 data1, data2 是读取的标注数据,根据不同情况,会存成不同格式 如果是json则直接保存json内存对象结构 如果是txt可能会进行一定的结构化解析存储 :param extdata: 可以存储一些扩展信息内容 :param fltr: filter的缩写,PathGroups 的过滤规则。一般用来进行图片匹配。 None,没有过滤规则,就算不存在slt格式的情况下,也会保留分组 'json'等字符串规则, 使用 select_group_which_hassuffix,必须含有特定后缀的分组 judge(k, v),自定义函数规则 :param slt: select的缩写,要选中的标注文件后缀格式 如果传入slt参数,该 Basic 基础类只会预设好 file 参数,数据部分会置 None,需要后续主动读取 >> BasicLabelData('textGroup/aabb', {'a.json': ..., 'a/1.json': ...}) >> BasicLabelData('textGroup/aabb', slt='json') >> BasicLabelData('textGroup/aabb', fltr='jpg', slt='json') # 只获取有对应jpg图片的json文件 >> BasicLabelData('textGroup/aabb', fltr='jpg|png', slt='json') """ # 1 基础操作 root = Dir(root) self.root, self.rp2data, self.extdata = root, relpath2data or {}, extdata or {} self.pathgs = None if relpath2data is not None or slt is None: return # 2 如果没有默认data数据,以及传入slt参数,则需要使用默认文件关联方式读取标注 relpath2data = {} gs = PathGroups.groupby(Dir(root).select_files('**/*')) if isinstance(fltr, str): gs = gs.select_group_which_hassuffix(fltr) elif callable(fltr): gs = gs.select_group(fltr) self.pathgs = gs # 3 读取数据 for stem, suffixs in tqdm(gs.data.items(), f'{self.__class__.__name__}读取数据', disable=not prt): f = File(stem, suffix=slt) if reads and f: # dprint(f) # 空json会报错:json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0) relpath2data[f.relpath(self.root)] = f.read() else: relpath2data[f.relpath(self.root)] = None self.rp2data = relpath2data