• crudini感悟


        闲来无事,在github上发现一个很有趣的project crudini,实现命令行对ini文件的增删改查和merge操作。起初会觉得至于如此小题大做么,但查阅之后,发现该项目对文件的操作比较精细,从文件锁FileLock、临时文件tempfile、SHA256 hashlib、退出执行atexit、shutil文件操作都使人眼前一亮。工程地址:https://github.com/joehakimrahme/crudini

    contextlib上下文管理器

      使用装饰器 contextlib.contextmanager() 将一个生成器函数转换为上下文管理器,在yield前,为前置操作,在__enter__中执行,yield为后置操作,在__exit__执行

    举个例子:

    import contextlib
    import os
    
    @contextlib.contextmanager
    def remove_file_on_error(path):
        try:
            print("befor yield...")
            yield
            print("after yield....")
        except Exception as e:
            if os.path.exists(path):
                os.unlink(path)
    
    with remove_file_on_error('caesar'):
        # some file operation
        print("d")
    

        在contextlib库的GeneratorContextManager中定义被装饰的方法,在__enter__时,调用生成器的next方法(self.gen.next),所以会执行yield前面的操作。在yield返回None之后,__enter__执行完毕。

    开始调用上下文的Body,即例子中的print("d")。调用完成后,继续调用GeneratorContextManager的__exit___方法(self.gen.next)执行yield的后面部分,完成后抛出StopIteration异常结束。

    在contextlib库中 contextmanager 中对GeneratorContextManager进行调用,形成装饰器,可以很方便实现上下文管理,更重要的是在方法前、方法后、异常中进行操作。

    在curlini中使用如下,对文件操作的上下文管理(创建临时文件、权限fchown修改,data写入、rename临时文件),如果出现异常,则删除临时文件

    python中os操作

    os.unlink(filepath)  删除filepath文件

    f=os.fileno() 获取文件对象,返回一个int数字,叫做文件描述符

    os.write(f, data) 向f 对象中写入data,os.flush()刷入文件, os.fsysn(f) 强制将文件描述符为f的文件刷入硬盘

    sys.stdin.read() 从输入流中读取数据,特别适合shell中使用"<" 流入的情况

    创建临时文件tempfile模块,在当前文件夹下创建一个"name.字符串.tmp" 的文件,文件为空

    (f, tmp) = tempfile.mkstemp(".tmp", prefix=name + ".", dir=".")

    文件锁

    在linux系统/proc/locks 下:

    第一列表示锁的类型,FLOCK和POSIX,第二列是建议性锁(不具备强制性。一个进程使用flock将文件锁住,另一个进程可以直接操作正在被锁的文件,修改文件中的数据,原因在于flock只是用于检测文件是否被加锁,针对文件已经被加锁,另一个进程写入数据的情况,内核不会阻止这个进程的写入操作,是建议性锁的内核处理策略。在这种情况,使用vim依然可以编辑文件,只对存在锁检查的进程进行阻塞。第四列表示使用这个锁的进程。

    如下:进程2223获取锁在执行操作,进程2279在等待,直到2223释放锁。

    在curlini中分别对windows和linux下的锁进行lock和unlock方法进行定义,如下:

    import os
    
    class FileLock(object):
        """Advisory file based locking.  This should be reasonably cross platform
           and also work over distributed file systems."""
        def __init__(self, fno, exclusive=False):
            # fno is FileObject
            self.fp = fno
            self.locked = False
    
            if os.name == 'nt':
                import msvcrt
    
                def lock(self):
                    msvcrt.locking(self.fp, msvcrt.LK_LOCK, 1)
                    self.locked = True
    
                def unlock(self):
                    if self.locked:
                        msvcrt.locking(self.fp, msvcrt.LK_UNLCK, 1)
                    self.locked = False
    
            else:
                import fcntl
    
                def lock(self):
                    operation = fcntl.LOCK_EX if exclusive else fcntl.LOCK_SH
                    fcntl.lockf(self.fp, operation)
                    self.locked = True
    
                def unlock(self):
                    if self.locked:
                        fcntl.lockf(self.fp, fcntl.LOCK_UN)
                    self.locked = False
    
            FileLock.lock = lock
            FileLock.unlock = unlock

    文件的SHA256

    在文件加锁以后,获取文件的data,计算sha256值。在通过命令行操作ini,将命令行中的数据,添加进data数据,获取sha256值。如果值相同,则不进行操作。

    def _chksum(self, data):
        h = hashlib.sha256()
        if sys.version_info[0] >= 3:
            h.update(bytearray(data, 'utf-8'))
        else:
            h.update(data)
        return h.digest()
  • 相关阅读:
    IIS7.5 部署WCF项目问题集锦
    C#制作“安装和部署”时,实现软件开机启动
    Strsafe.h:更安全的C语言字符串处理函数
    FMOD音频引擎简单使用
    您也使用托管C++吗?
    《Programming in Lua中文版》 8.Compilation, Execution, and Errors
    恶心的C语言strtok函数
    Lua一些基本函数
    Lua tables 分析1
    如何让EditPlus支持LUA(转)
  • 原文地址:https://www.cnblogs.com/CaesarLinsa/p/10802347.html
Copyright © 2020-2023  润新知