【Python|第39期】监听目录取消文件只读属性

日期:2023年7月17日
作者:Commas
签名:(ง •_•)ง 积跬步以致千里,积小流以成江海……
注释:如果您觉得有所帮助,帮忙点个赞,也可以关注我,我们一起成长;如果有不对的地方,还望各位大佬不吝赐教,谢谢^ - ^
1.01365 = 37.7834;0.99365 = 0.0255
1.02365 = 1377.4083;0.98365 = 0.0006


文章目录

  • 一、精彩回顾
  • 二、前言
  • 二、第三方监听目录变化库
    • (1)Watchdog库
    • (2)Pyinotify库
    • (3)Gamin库
    • (4)PyFilesystem2库
  • 三、监听目录取消文件只读
    • (1)首先,安装watchdog库
    • (2)取消文件只读属性
    • (3)事件处理器对象
    • (4)观察者对象
  • 四、最终实现的代码


【Python|第39期】监听目录取消文件只读属性_第1张图片


一、精彩回顾

《Python学习的奇妙之旅》
《python3遍历目录的三种方法浅谈》
《python设置文件只读与取消文件只读》
《Python读取文件的三种方式》

二、前言

通过新版微信接收的文件都被修改了权限,文件均被设置为“只读”。或许这对于微信来说是挺安全的,但是却给我们带来了不少的麻烦,想修改点东西,必须先取消文件只读属性,否者无法保存。

前段时间写过关于文件权限的文章(《python设置文件只读与取消文件只读》,结合目录遍历的知识(《python3遍历目录的三种方法浅谈》),再加个定时器不断遍历 微信接收文件的目录 ,确实可以解决问题,但不是本文所要讲解的,感兴趣的小伙伴可以自行尝试下。

虽然微信版本在持续更新,但是“文件被设为只读”的行为却没有更改,看来只能用程序打败程序,监听微信接收文件的目录,接收一个文件就处理一个文件的方式,去解决文件只读的问题。

二、第三方监听目录变化库

Python 的标准库中,没有直接用于监听文件目录变化的内置模块。有几个流行的第三方库可以用于监听文件目录的变化,如下:

(1)Watchdog库

Watchdog 是一个功能强大且易于使用的库,提供了监视文件和目录变化的功能。它支持各种事件,如文件创建、修改、删除等,并可以在这些事件发生时执行自定义的回调函数。Watchdog库在 Python 社区中广泛使用,并且有良好的文档和示例代码。

(2)Pyinotify库

Pyinotify 是一个与 Linux 内核中的 inotify 机制集成的库,可以高效地监视文件和目录的变化。它提供了 PythonicAPI,可以轻松地处理文件事件。Pyinotify 对于需要在Linux平台上进行文件监控的任务非常有用。

(3)Gamin库

Gamin 是另一个用于文件监控的库,它使用 Linux 上的 Gamin 守护进程作为后端。Gamin 库提供了一个简单的接口来监视文件和目录的变化,并可以触发相应的事件。

(4)PyFilesystem2库

PyFilesystem2 是一个通用的文件系统抽象库,它可以处理各种文件系统和存储。虽然它的主要目的是提供一个统一的 API 来访问不同类型的文件系统,但它也具有监视文件变化的功能。

三、监听目录取消文件只读

为了简化开发,这里打算采用第三方库 watchdog 来实现我们的需求。

(1)首先,安装watchdog库

pip install watchdog

如果不想污染全局库,想安装在虚拟环境中,可以这样做:

  • 首先,创建一个虚拟环境 chmod_watchdogvirtualenv chmod_watchdog
  • 其次,激活z虚拟环境,\chmod_watchdog\Scripts\activate
  • 接着,安装 watchdog 库,pip install watchdog
  • 完成工作并想要退出虚拟环境,\chmod_watchdog\Scripts\deactivate

【Python|第39期】监听目录取消文件只读属性_第2张图片

(2)取消文件只读属性

  • 判断文件是否只读
def is_file_read_only(file_path):

    if os.access(file_path, os.W_OK):
    	# 如果文件或目录具有指定的权限,返回True。
        return False
    else:
    	# 如果文件或目录不具有指定的权限,
    	# 或者检查过程中发生错误,返回False。
        return True
  • 取消文件的只读属性
def unset_file_read_only(file_path):
    # 获取当前文件的权限标志位
    file_stat = os.stat(file_path)
    
    # 取消只读属性,将其权限更改为可写
    new_mode = file_stat.st_mode | stat.S_IWUSR
    
    # 设置新的权限标志位
    os.chmod(file_path, new_mode)

(3)事件处理器对象

  • 创建事件处理器对象
class MyEventHandler(FileSystemEventHandler):
    def on_any_event(self, event):
        if event.is_directory:  # 忽略文件夹的变化
            return
        if event.event_type == 'created' or event.event_type == 'modified':  # 只处理新建和修改事件
            file_path = event.src_path
            remove_read_only(file_path)

event_handler = MyEventHandler()
  • 取消文件只读属性,函数会在文件变化时被调用
def remove_read_only(file_path):
    # file_path 参数是变化的文件路径
    print("文件已变化:", file_path)

    # 判断文件是否只读
    if is_file_read_only(file_path):
        # 文件是只读的
        # 取消文件的只读属性
        unset_file_read_only(file_path)
    else:
        # 文件不是只读的
        pass

(4)观察者对象

  • 创建观察者对象
observer = Observer()
  • 将自定义的事件处理器和要监视的目录绑定在一起
    event_handler:我们定义的自定义事件处理器的实例;
    directory:需要监视的目录路径;
    recursive=True 表示要递归地监视目录中的子目录。
observer.schedule(event_handler, directory, recursive=True)
  • 启动观察器,开始监听目录的变化
observer.start()
  • 保持文件监视器(Observer)持续运行,并在收到键盘中断信号(KeyboardInterrupt)时停止监视器的运行。
try:
    # 使用无限循环来保持观察器持续运行
    while True:
        # 在每次循环中,使用time.sleep(1)函数暂停1秒钟,以避免过度消耗CPU资源。
        time.sleep(1)
except KeyboardInterrupt:
    # 如果在循环中按下Ctrl+C,会引发KeyboardInterrupt异常。
    # 在异常处理块中,调用observer.stop()方法停止观察器的运行。
    observer.stop()
  • 等待观察器线程的结束
observer.join()

最后,将其封装成一个监听目录的函数 start_monitoring(directory),具体如下所示:

# 监听目录的函数
def start_monitoring(directory):

    # 创建事件处理器对象
    event_handler = MyEventHandler()

    # 创建观察者对象
    observer = Observer()
    # 将自定义的事件处理器和要监视的目录绑定在一起
    observer.schedule(event_handler, directory, recursive=True)
    # 启动观察器,开始监听目录的变化
    observer.start()

    try:
        # 使用无限循环来保持观察器持续运行
        while True:
            # 在每次循环中,使用time.sleep(1)函数暂停1秒钟,以避免过度消耗CPU资源。
            time.sleep(1)
    except KeyboardInterrupt:
        # 如果在循环中按下Ctrl+C,会引发KeyboardInterrupt异常。
        # 在异常处理块中,调用observer.stop()方法停止观察器的运行。
        observer.stop()

    # 等待观察器线程的结束
    observer.join()

四、最终实现的代码

【Python|第39期】监听目录取消文件只读属性_第3张图片
打开微信,确定自己微信的文件管理路径 E:\WeChat Files\,接着开启监听 start_monitoring("E:/WeChat Files/"),就可以实现接收文件后立马自动取消文件只读属性啦,源码如下所示:

# coding:utf-8

import os,stat
import time
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler

# 判断文件是否只读
def is_file_read_only(file_path):
    if os.access(file_path, os.W_OK):
    	# 如果文件或目录具有指定的权限,返回True。
        return False
    else:
    	# 如果文件或目录不具有指定的权限,
    	# 或者检查过程中发生错误,返回False。
        return True

# 取消文件的只读属性
def unset_file_read_only(file_path):
    # 获取当前文件的权限标志位
    file_stat = os.stat(file_path)
    
    # 取消只读属性,将其权限更改为可写
    new_mode = file_stat.st_mode | stat.S_IWUSR
    
    # 设置新的权限标志位
    os.chmod(file_path, new_mode)
    print("取消文件只读属性:",file_path)

# 取消文件只读属性,函数会在文件变化时被调用
def remove_read_only(file_path):
    # file_path 参数是变化的文件路径
    print("文件已变化:", file_path)

    # 判断文件是否只读
    if is_file_read_only(file_path):
        # 文件是只读的
        # 取消文件的只读属性
        unset_file_read_only(file_path)
    else:
        # 文件不是只读的
        pass

class MyEventHandler(FileSystemEventHandler):
    def on_any_event(self, event):
        print("event_type:",event.event_type)
        if event.is_directory:  # 忽略文件夹的变化
            return
        if event.event_type == 'created' or event.event_type == 'modified':  # 只处理新建和修改事件
            file_path = event.src_path
            remove_read_only(file_path)

# 监听目录的函数
def start_monitoring(directory):

    # 创建事件处理器对象
    event_handler = MyEventHandler()

    # 创建观察者对象
    observer = Observer()
    # 将自定义的事件处理器和要监视的目录绑定在一起
    observer.schedule(event_handler, directory, recursive=True)
    # 启动观察器,开始监听目录的变化
    observer.start()

    try:
        # 使用无限循环来保持观察器持续运行
        while True:
            # 在每次循环中,使用time.sleep(1)函数暂停1秒钟,以避免过度消耗CPU资源。
            time.sleep(1)
    except KeyboardInterrupt:
        # 如果在循环中按下Ctrl+C,会引发KeyboardInterrupt异常。
        # 在异常处理块中,调用observer.stop()方法停止观察器的运行。
        observer.stop()

    # 等待观察器线程的结束
    observer.join()

if __name__ == "__main__":
    # 获取要监听的文件夹路径
    # NO1:OK
    directory = 'E:/WeChat Files'
    # directory = 'E:/WeChat Files/'
    # NO2:OK
    # directory = 'E:\\WeChat Files'
    # NO3:Fail
    # directory = 'E:\WeChat Files'


    # 开启监听,满足条件就取消文件只读属性
    start_monitoring(directory)

我的微信公众号【会飞的小猴子】,等你来关注哦 ^ - ^


参考文章:

  • 《python设置文件只读与取消文件只读》
  • 《python文件监控模块Watchdog使你的文件管理更轻松》

版权声明:本文为博主原创文章,如需转载,请给出:
原文链接:https://blog.csdn.net/qq_35844043/article/details/131749805

你可能感兴趣的:(Python3,python,开发语言,Watchdog库,文件只读,监听目录变化)