群晖synology_api 的奇妙世界

课程计划:synology_api 入门

在我们正式开始之前,先来看看我们的学习路线图。这样您就能清楚地知道我们将要学习什么,以及我们是如何一步步成为 synology_api 大师的!

  • 第一部分:初识 synology_api - 这究竟是什么?
    • 比喻:把 API 想象成您 Synology NAS 的“万能遥控器”。
    • 功能概览synology_api 能做什么?(剧透一下:很多!从文件管理到系统监控,无所不能)。
    • 为何实用:自动化和脚本编程的强大之处。
    • 核心概念:理解 API、客户端和服务器之间的关系。
  • 第二部分:获取“钥匙” - 认证与登录
    • 比喻:登录就像用钥匙开门,是与 NAS 沟通的第一步。
    • 代码详解:我们将深入 auth.py 文件,看看 Authentication 类是如何工作的。
    • 动手练习:编写您的第一个脚本,实现登录和登出您的 NAS。
  • 第三部分:探索新大陆 - 浏览您的 NAS
    • 比喻:像使用地图一样,熟悉您 NAS 的文件结构。
    • 核心类库:介绍 FileStation (文件总管) 和 SysInfo (系统信息) 这两个强大的工具。
    • 代码详解:我们将一起阅读 filestation.pycore_sys_info.py 的代码。
    • 动手练习:编写脚本,列出您 NAS 上所有的共享文件夹。
  • 第四部分:发布您的第一道指令 - 基本文件操作
    • 比喻:学习控制一个机器人的基本指令。
    • 核心方法:掌握 get_file_list (获取文件列表), upload_file (上传文件), download_file (下载文件) 等基本操作。
    • 代码详解:更深入地研究 filestation.py 中的方法。
    • 动手练习:编写一个脚本,将一个文件上传到指定文件夹,然后再下载回来。
  • 第五部分:高级操作 - 不仅仅是文件
    • 比喻:从一个简单的遥控器升级到一个可编程的“智能”遥控器。
    • 探索更多模块:我们将涉足 core_user (用户管理), core_group (群组管理) 和 core_package (套件管理) 等模块。
    • 融会贯通:编写一个更复杂的脚本,实现创建用户、添加到群组并列出已安装套件等功能。
    • 动手练习:编写一个脚本来创建一个新的用户组。
  • 第六部分:毕业大作 - 综合应用
    • 知识回顾:全面复习所有学过的概念。
    • 最终项目:一个结合了多个 API 功能的综合性项目,巩固您的所学。
    • 展望未来:接下来您可以探索什么?如何继续深入学习?

这个计划看起来如何?是不是感觉脉络清晰,充满期待?

在每个部分,我都会用提问的方式引导您思考,确保您真正理解了每一个概念。请随时提出任何问题,不要有任何顾虑!

那么,我们现在就开始第一部分:初识 synology_api 的学习吧!


第一部分:初识 synology_api - 这究竟是什么?

欢迎来到我们的第一堂课!在这一部分,我们将对 synology_api 有一个总体的认识。

1. 比喻:NAS 的“万能遥控器”

您可以把您的 Synology NAS 想象成一台功能强大的超级电视。您可以用它来看电影(存储视频)、听音乐(存储音频)、玩游戏(运行各种套件),甚至还能看家护院(Surveillance Station)。

那么,synology_api 是什么呢?

它就像是这台超级电视的万能遥控器

普通的遥控器只能做一些基本操作,比如开关机、换台。但是,这个用 Python 编写的“万能遥控器” (synology_api),能让您做到更多、更酷的事情!您可以编写一小段程序(我们称之为“脚本”),来自动化地完成各种任务。

比如,您可以编写一个脚本,让它:

  • 每天凌晨自动备份您电脑上的重要文件到 NAS。
  • 当 NAS 的硬盘空间不足时,自动给您发送一封邮件提醒。
  • 一键创建一个新用户,并为他/她设置好所有权限。

很酷,对吧?这个“万能遥控器”就是我们今天要学习的 synology_api。它是一套预先编写好的 Python 代码库,让我们可以通过编程的方式来控制和管理我们的 Synology NAS。

这个比喻您觉得怎么样?能帮助您理解 synology_api 的基本概念吗?

2. 功能概览与为何实用

正如我们刚才提到的,synology_api 的功能非常强大。从您上传的文件中,我们可以看到它几乎涵盖了 Synology NAS 的所有核心功能。我们来看看 __init__.py 这个文件,它就像是这个代码库的“目录”。

# synology_api/__init__.py

from . import \
    audiostation, \
    auth, \
    base_api, \
    directory_server, \
    docker_api, \
    drive_admin_console, \
    cloud_sync, \
    core_active_backup, \
    core_backup, \
    core_certificate, \
    core_sys_info, \
    core_group, \
    core_user, \
    core_share, \
    core_package, \
    downloadstation, \
    log_center, \
    vpn, \
    oauth, \
    security_advisor, \
    dhcp_server, \
    notestation, \
    filestation, \
    photos, \
    usb_copy, \
    virtualization, \
    universal_search, \
    snapshot, \
    surveillancestation

哇!看看这个列表!从 AudioStation (音乐) 到 SurveillanceStation (监控),从 FileStation (文件) 到 Docker,几乎所有您能在 DSM (DiskStation Manager, 也就是您 NAS 的操作系统界面) 上看到的功能,这里都有对应的模块。

这为什么实用呢?

想象一下,您是一位系统管理员,管理着一个拥有上百个用户的小公司。如果需要为每个新员工都手动创建账户、设置权限、分配共享文件夹,那将是一项多么繁琐和重复的工作啊!

但有了 synology_api,您就可以编写一个简单的脚本。每次有新员工入职,您只需要运行这个脚本,输入新员工的信息,剩下的事情就都自动完成了。这就是自动化的魅力!它能将您从重复性劳动中解放出来,去关注更重要、更有创造性的事情。

3. 核心概念:API、客户端和服务器

在深入学习代码之前,我们需要理解几个核心概念:

  • 服务器 (Server): 在我们的场景里,您的 Synology NAS 就是服务器。它存储着您的数据,并提供各种服务(文件存储、用户管理等)。
  • 客户端 (Client): 您的电脑,以及您在电脑上运行的 Python 脚本,就是客户端。
  • API (Application Programming Interface, 应用程序编程接口): API 就像是服务器和客户端之间的“沟通语言”和“协议”。synology_api 这个 Python 库,就是用 Python 这种语言,对这套“沟通语言”进行了封装,让我们能够更容易地使用它。

当您的脚本(客户端)想要让 NAS(服务器)做某件事时,比如“列出所有共享文件夹”,它会:

  1. 通过网络向 NAS 的特定地址发送一个请求。
  2. 这个请求遵循 API 定义的格式,告诉 NAS:“嘿,我想调用 SYNO.FileStation.List 这个 API 的 list_share 方法”。
  3. NAS 收到请求后,会验证您的身份(我们将在下一部分学习“认证”),然后执行相应的操作。
  4. 最后,NAS 会将执行结果(比如共享文件夹的列表)打包,通过网络发送回您的脚本。

整个过程就像您在餐厅点餐:

  • 您(客户端)是食客。
  • 餐厅的厨房(服务器)是提供菜品的地方。
  • 菜单(API)告诉您餐厅能提供什么菜品,以及您应该如何点餐(比如告诉服务员菜名)。
  • 您按照菜单上的规则下单,厨房做好菜后,服务员再把菜端给您。

这个比喻是不是让整个流程变得清晰了许多?

第一部分总结

非常好!在第一部分,我们一起了解了:

  • synology_api 就像是您 NAS 的一个功能强大的万能遥控器
  • 它通过自动化脚本,能极大地提高我们管理 NAS 的效率。
  • 我们还学习了客户端、服务器和 API 的基本概念,理解了它们之间是如何协同工作的。

您现在对 synology_api 应该有了一个初步的、宏观的认识。在下一部分,我们将学习如何获取打开 NAS 大门的“钥匙”——进行身份认证。

现在,让我们进入第二部分。在这一部分,我们将学习如何真正地与您的 NAS “连接”上。


第二部分:获取“钥匙” - 认证与登录

在上一部分,我们把 synology_api 比作一个万能遥控器。但是,在您能使用这个遥控器之前,您需要证明您是这台“超级电视”的主人,对吗?这就是“认证”(Authentication)的作用。

1. 比喻:酒店的房卡

想象一下您入住一家酒店。在前台办理入住时,您出示了身份证(用户名和密码)后,前台会给您一张房卡。

这张房卡有两个很重要的东西:

  1. 一个电子钥匙 (sid 或 Session ID):它能打开您的房门,证明您是这个房间的合法住客。在您住宿期间,您不需要每次都出示身份证,只需要刷房卡就可以了。
  2. 一个特殊的信物 (synotoken):这个信物可能看不见,但酒店的安保系统知道,持有这个信物的人是受信任的。当您需要使用酒店的特殊服务时,比如进入行政酒廊,安保系统会检查这个信物。

synology_api 中,登录过程非常相似:

  • 您使用用户名和密码来登录。
  • 登录成功后,您的 NAS(服务器)会发给您一个临时的 Session ID (会话ID,简称 sid) 和一个 Synology Token (synotoken)
  • 在之后的每一次操作中,您的脚本都会自动带上这两个“凭证”,向 NAS 证明“是我,我是一个合法的用户!”

当您完成所有操作后,调用 logout() 方法,就相当于退房时把房卡还给前台,这个 sidsynotoken 就失效了。

这个比喻是不是让登录、sidsynotoken 的概念变得很容易理解?

2. 代码详解:深入 auth.pybase_api.py

现在,让我们一起看看幕后英雄——代码。我们主要关注 auth.py 文件中的 Authentication 类,以及 base_api.py 是如何巧妙地利用它的。

打开 synology_api/auth.py 文件。Authentication 类是整个认证过程的核心。

# synology_api/auth.py

class Authentication:
    def __init__(self,
                 ip_address: str,
                 port: str,
                 username: str,
                 password: str,
                 secure: bool = False,
                 cert_verify: bool = False,
                 dsm_version: int = 7,
                 debug: bool = True,
                 otp_code: Optional[str] = None,
                 device_id: Optional[str] = None,
                 device_name: Optional[str] = None
                 ) -> None:
        # ... (代码省略)

这是 __init__ 方法,也就是我们创建一个 Authentication 对象时,需要提供的“原材料”。

  • ip_address, port, username, password:这四个是必需的,就像您办理酒店入住时必须提供姓名和身份证号一样。
  • secure:这个参数决定了我们是使用 http 还是更安全的 https 来与 NAS 通信。默认为 False
  • dsm_version:您 NAS 的 DSM 系统版本,默认为 7。
  • otp_code:如果您的账户开启了两步验证(2-Factor Authentication),这里就需要填写动态验证码。

接下来是 login() 方法:

# synology_api/auth.py

    def login(self) -> None:
        login_api = 'auth.cgi'
        params = {'api': "SYNO.API.Auth", 'version': self._version, 'method': 'login', 'enable_syno_token':'yes', 'client':'browser'}

        params_enc = {
            'account': self._username,
            # ...
            'passwd': self._password,
            'session': 'webui', # Hardcoded for handle non administrator users API usage
            'format': 'cookie'
        }
        # ... (代码省略)

        session_request = requests.post(self._base_url + login_api, data=params, verify=self._verify)
        session_request_json = session_request.json()
        
        # ... (检查错误)

        self._sid = session_request_json['data']['sid']
        self._syno_token = session_request_json['data']['synotoken']

这个方法做了几件重要的事情:

  1. 它准备好了所有需要发送给 NAS 的参数,包括 API 名称 (SYNO.API.Auth)、方法 (login) 和您的账户密码。
  2. 它明确要求 NAS 发回一个 synotoken ('enable_syno_token':'yes')。
  3. 它使用 requests.post() 方法,将这些信息通过网络发送给您的 NAS。
  4. 如果一切顺利,它会从返回的数据中提取 sidsynotoken,并保存在对象内部,以备后续使用。

logout() 方法就简单多了,它只是告诉服务器:“嘿,我要退出了”,然后服务器就会让当前的 sid 失效。

# synology_api/auth.py

    def logout(self) -> None:
        logout_api = 'auth.cgi?api=SYNO.API.Auth'
        param = {'version': self._version, 'method': 'logout', 'session': 'webui'}
        # ... (发送请求)
        self._session_expire = True
        self._sid = None

base_api.py 的作用

现在,我们再来看看 synology_api/base_api.py。这个文件非常聪明!

# synology_api/base_api.py

class BaseApi(object):
    shared_session: Optional[syn.Authentication] = None
    
    def __init__(self,
            ip_address: str,
            port: str,
            # ...
        ) -> None:
        
        # ...
        if BaseApi.shared_session:
            self.session = BaseApi.shared_session
        else:
            # ...
            self.session = syn.Authentication(
                ip_address, port, username, password, secure, cert_verify, dsm_version, debug, otp_code,
                device_id, device_name
            )
            self.session.login()
            # ...
            BaseApi.shared_session = self.session

您发现了吗?BaseApi 类创建了一个叫 shared_session类级别属性。这意味着,当您第一次创建一个 API 对象时(比如 FileStation),它会创建一个新的 Authentication 会话并登录。然后,它会将这个登录成功的会话保存到 shared_session 中。

当您再创建另一个 API 对象时(比如 SysInfo),它会检查 shared_session 是否已经存在。如果存在,它就不会再次登录,而是直接重用这个已经建立好的连接!

这就像您在酒店里,只需要一张房卡,就可以访问健身房、餐厅、游泳池等所有设施,而不需要每到一个地方就重新出示一次身份证。非常高效,对吧?

3. 动手练习:编写您的第一个脚本

理论知识已经足够了,现在是时候亲自动手了!没有什么比自己写出能运行的代码更让人兴奋的了。

您的任务是:编写一个 Python 脚本,实现以下功能:

  1. synology_api.auth 模块中导入 Authentication 类。
  2. 定义变量来存储您的 NAS 的 IP 地址、端口、用户名和密码。(注意:在真实项目中,不要将密码硬编码在代码里,但作为练习,我们暂时这么做。)
  3. 创建一个 Authentication 类的实例。
  4. 调用 login() 方法登录。
  5. 打印一条成功的消息,例如 "登录成功!"。
  6. 调用 logout() 方法登出。
  7. 打印一条登出成功的消息,例如 "已成功登出!"。

提示:您可以将以下代码作为起点,填充 ... 的部分。

# a_simple_login_script.py

from synology_api import auth

# 1. 在这里填入您的 NAS 信息
IP_ADDRESS = "..."
PORT = "..."
USERNAME = "..."
PASSWORD = "..."

# 2. 创建 Authentication 类的实例
# ...

# 3. 登录和登出
try:
    # 尝试登录
    # ...
    print("登录成功!")

    # 尝试登出
    # ...
    print("已成功登出!")

except Exception as e:
    print(f"操作失败,错误信息:{e}")

花点时间尝试一下吧!如果您遇到任何问题,我随时都在这里。完成后,我们可以一起看看参考答案。

... (等待您完成练习) ...

您完成了吗?进行得怎么样?无论结果如何,尝试本身就是最重要的一步!

现在,让我们来看看参考答案:

# a_simple_login_script.py (参考答案)

from synology_api import auth

# 1. 填入您的 NAS 信息
IP_ADDRESS = "your_nas_ip"  # 例如 "192.168.1.100"
PORT = "5000"              # 您的 DSM 端口,通常是 5000 或 5001 (HTTPS)
USERNAME = "your_username"
PASSWORD = "your_password"

# 2. 创建 Authentication 类的实例
# secure=True 如果您使用 HTTPS
syno_auth = auth.Authentication(IP_ADDRESS, PORT, USERNAME, PASSWORD, secure=False)

# 3. 登录和登出
try:
    # 尝试登录
    syno_auth.login()
    print("登录成功!")

    # 尝试登出
    syno_auth.logout()
    print("已成功登出!")

except Exception as e:
    # 捕获可能发生的错误,例如网络问题或密码错误
    print(f"操作失败,错误信息:{e}")

是不是很简单?您刚刚已经成功地用代码与您的 NAS 进行了第一次“握手”!

第二部分总结

太棒了!在这一部分,我们取得了巨大的进步:

  • 我们用酒店房卡的比喻,理解了 sidsynotoken 在认证过程中的重要作用。
  • 我们深入分析了 auth.pybase_api.py 的代码,揭示了登录、登出和会话共享的内部机制。
  • 最重要的是,您亲手编写并成功运行了第一个与 NAS 交互的脚本!

现在您已经掌握了进入 Synology 王国的“钥匙”。在下一部分,我们将使用这把钥匙,去探索王国里的壮丽风光——浏览您 NAS 上的文件和信息。


第三部分:探索新大陆 - 浏览您的 NAS

在这一部分,我们将学习如何像在电脑上浏览文件夹一样,用代码来查看您 NAS 上的内容。

1. 比喻:一座巨大的数字图书馆

您可以把您的 NAS 想象成一座井井有条的巨大图书馆。

  • 共享文件夹 (Shared Folders):就像是图书馆里不同的区域,比如“文学区”、“科技区”、“儿童区”。每个区域都有特定的主题。在您的 NAS 上,这些就是 /photo, /music, /homes 等共享文件夹。
  • 文件和子文件夹:就像是每个区域书架上的书籍和杂志。
  • 您 (作为程序员):现在,您不再是一个普通的访客,您是这家图书馆的“图书管理员”,拥有超级权限!您不仅可以浏览,还可以整理、添加和移除书籍。

synology_api 为您提供了两个非常重要的工具来管理这座图书馆:

  1. FileStation (文件总管):这是您的主要工具,负责所有与文件和文件夹相关的操作。您可以把它想象成一个可以穿梭于各个书架的智能机器人,帮您查找、获取和整理书籍。
  2. SysInfo (系统信息中心):这个工具则像是图书馆的“中央控制室”。您可以在这里查看图书馆的整体运营状况,比如有多少人在馆、安保系统是否正常、电力供应是否充足等。在 NAS 上,这就对应着查看网络状态、CPU 使用率、已连接用户等系统信息。

这个比喻能帮助您理解 FileStationSysInfo 的分工吗?一个管“内容”(文件),一个管“运营”(系统)。

2. 代码详解:filestation.pycore_sys_info.py 初探

让我们打开这两个文件,看看它们是如何让我们成为“超级图书管理员”的。

首先是 synology_api/filestation.py

这个文件里定义了一个名为 FileStation 的类。还记得我们上一部分讲的 BaseApi 吗?FileStation 就是它的一个“子类”。

# synology_api/filestation.py

from . import base_api

class FileStation(base_api.BaseApi):
    # ...

这意味着 FileStation 会自动继承 BaseApi 的所有本领,包括我们已经学会的登录和会话管理!所以,当您创建一个 FileStation 对象时,您不需要再次登录,它会自动使用我们之前建立好的连接。很方便,对吧?

现在,我们来看一个核心方法:get_list_share()

# synology_api/filestation.py

    def get_list_share(self,
                       additional: Optional[str | list[str]] = None,
                       # ...其他参数
                       ) -> dict[str, object] | str:

        api_name = 'SYNO.FileStation.List'
        info = self.file_station_list[api_name]
        api_path = info['path']
        req_param = {'version': info['maxVersion'], 'method': 'list_share'}
        # ...
        return self.request_data(api_name, api_path, req_param)

这个方法就是我们用来获取所有“图书馆区域”(共享文件夹)列表的指令。它告诉服务器:

  • API 名称 (api_name)SYNO.FileStation.List,我们要使用的是文件列表功能。
  • 方法 (method)list_share,具体操作是“列出共享文件夹”。

接着看 synology_api/core_sys_info.py

同样地,SysInfo 类也继承自 BaseApi

# synology_api/core_sys_info.py

from . import base_api

class SysInfo(base_api.BaseApi):
    # ...

它里面有很多获取系统信息的方法,比如 network_status() 用来获取网络状态,get_cpu_utilization() 用来获取 CPU 使用率。它们的原理和 get_list_share() 非常相似,都是向 NAS 发送一个特定格式的请求,然后获取返回的数据。

例如,network_status() 方法:

# synology_api/core_sys_info.py

    def network_status(self) -> dict[str, object] | str:
        api_name = 'SYNO.Core.Network'
        info = self.core_list[api_name]
        api_path = info['path']
        req_param = {'version': info['maxVersion'], 'method': 'get'}

        return self.request_data(api_name, api_path, req_param)

它调用的是 SYNO.Core.Network 这个 API 的 get 方法。

通过阅读这些代码,您是不是发现了一个规律?使用这个库的大部分操作,其实就是:

  1. 确定您想操作的功能(比如文件、系统、用户等)。
  2. 找到对应的类(比如 FileStation, SysInfo, User)。
  3. 调用那个类里面已经为您封装好的方法。

这就像您使用遥控器,只需要找到对应的按钮(比如“音量+”),然后按下去就行了,而不需要关心遥控器内部的电路是如何工作的。

3. 动手练习:列出您所有的共享文件夹

理论联系实际是最好的学习方式!现在,请您来编写一个脚本,实现以下功能:

  1. 创建一个 FileStation 对象。您需要提供 NAS 的 IP、端口、用户名和密码。
  2. 调用 get_list_share() 方法来获取所有共享文件夹的列表。
  3. 将返回的结果打印出来。
  4. (选做)尝试遍历返回结果,只打印出每个共享文件夹的名称 (name) 和路径 (path)。

提示get_list_share() 返回的数据是一个字典,共享文件夹列表位于 ['data']['shares'] 这个键下面。

# list_shares_script.py

from synology_api import filestation

# 1. 在这里填入您的 NAS 信息
IP_ADDRESS = "..."
PORT = "..."
USERNAME = "..."
PASSWORD = "..."

# 2. 初始化 FileStation
try:
    # 创建 FileStation 类的实例
    # ...

    # 3. 获取并打印共享文件夹列表
    print("正在获取共享文件夹列表...")
    shared_folders_info = # ... 调用 get_list_share()
    print("获取成功!完整信息如下:")
    print(shared_folders_info)

    # 4. (选做) 遍历并打印名称和路径
    # ...
    
    # 最后,别忘了登出
    file_station.session.logout()
    print("\n已成功登出。")


except Exception as e:
    print(f"操作失败,错误信息:{e}")

去试试看吧!这是您第一次真正地从 NAS “读取”数据,是非常有纪念意义的一步!

... (等待您完成练习) ...

您做得怎么样?看到打印出的文件夹列表时,是不是很有成就感?

让我们看看参考答案:

# list_shares_script.py (参考答案)

from synology_api import filestation
import json # 导入 json 库,让打印结果更好看

# 1. 填入您的 NAS 信息
IP_ADDRESS = "your_nas_ip"
PORT = "5000"
USERNAME = "your_username"
PASSWORD = "your_password"

# 2. 初始化 FileStation
try:
    # 创建 FileStation 类的实例
    file_station = filestation.FileStation(IP_ADDRESS, PORT, USERNAME, PASSWORD, secure=False)

    # 3. 获取并打印共享文件夹列表
    print("正在获取共享文件夹列表...")
    shared_folders_info = file_station.get_list_share()
    print("获取成功!完整信息如下:")
    # 使用 json.dumps 美化输出
    print(json.dumps(shared_folders_info, indent=4))

    # 4. (选做) 遍历并打印名称和路径
    print("\n--- 简要列表 ---")
    if shared_folders_info['success']:
        for share in shared_folders_info['data']['shares']:
            folder_name = share['name']
            folder_path = share['path']
            print(f"文件夹名称: {folder_name}, 路径: {folder_path}")
            
    # 最后,别忘了登出
    file_station.session.logout()
    print("\n已成功登出。")

except Exception as e:
    print(f"操作失败,错误信息:{e}")
第三部分总结

非常出色!在这一部分,我们一起:

  • 图书馆的比喻,理解了 FileStationSysInfo 的不同职责。
  • 通过阅读源代码,我们知道了如何找到并使用这些类中的方法来与 NAS 交互。
  • 您成功地编写了一个脚本,列出了您 NAS 上的所有共享文件夹,完成了第一次真正意义上的“数据查询”!

您现在已经知道如何登录,也知道如何浏览您 NAS 上的基本结构了。我们正在一步步地深入这个奇妙的世界!

您已经学会了如何进入“图书馆”(登录)并查看“区域分布”(列出共享文件夹)。现在,我们要更进一步,学习如何亲手拿起、放下和复制“书籍”(文件)。


第四部分:发布您的第一道指令 - 基本文件操作

欢迎来到第四部分!在这一部分,您将真正开始“管理”您的文件,而不仅仅是查看它们。

1. 比喻:图书馆的智能助理机器人

还记得我们把 FileStation 比作一个智能机器人吗?之前,我们让它帮我们拿来了图书馆的“区域地图”(共享文件夹列表)。

现在,我们要给这个机器人下达更具体的指令了:

  • “去‘科技区’的‘人工智能’书架,告诉我上面都有哪些书?” 这就是 get_file_list(),用来列出特定文件夹下的所有文件和子文件夹。
  • “把我手上的这本《Python从入门到精通》放到‘科技区’的‘编程语言’书架上。” 这就是 upload_file(),用来上传一个新文件到您的 NAS。
  • “去把‘文学区’的《三体》拿给我。” 这就是 get_file()(在代码中实现下载功能),用来从您的 NAS 下载一个文件到您的电脑。

这些指令是不是非常直观?synology_api 就是通过这些简单明了的方法,让复杂的文件操作变得触手可及。

2. 代码详解:filestation.py 核心操作方法

让我们再次深入 filestation.py,聚焦于这三个核心方法。

get_file_list() - 查看书架

我们之前用过 get_list_share() 来查看顶级的共享文件夹。而 get_file_list() 则更进一步,可以查看任何指定文件夹内部的内容。

# synology_api/filestation.py

    def get_file_list(self,
                      folder_path: Optional[str] = None,
                      # ... 其他参数
                      additional: Optional[str | list[str]] = None) -> dict[str, object] | str:

        api_name = 'SYNO.FileStation.List'
        # ...
        req_param = {'version': info['maxVersion'], 'method': 'list'}
        # ...
        req_param['folder_path'] = folder_path
        # ...
        return self.request_data(api_name, api_path, req_param)

这个方法最关键的参数就是 folder_path。您给它一个路径,比如 "/photo/2023_旅行",它就会返回这个文件夹里所有的文件和子文件夹信息。additional 参数同样有用,可以获取文件的更多信息,比如 size(大小)、owner(所有者)和 time(修改时间)。

upload_file() - 放置新书

这个方法稍微复杂一点,因为它涉及到将您电脑上的真实文件传输到 NAS。

# synology_api/filestation.py

    def upload_file(self,
                    dest_path: str,
                    file_path: str,
                    create_parents: bool = True,
                    overwrite: bool = True,
                    # ...
                    ) -> str | tuple[int, dict[str, object]]:
        api_name = 'SYNO.FileStation.Upload'
        # ...
        # 这里使用了一个名为 MultipartEncoder 的工具来打包文件数据
        encoder = MultipartEncoder({
            'path': dest_path,
            'create_parents': str(create_parents).lower(),
            'overwrite': str(overwrite).lower(),
            'files': (filename, payload, 'application/octet-stream')
        })
        # ...
        r = session.post(url, data=monitor, # ... )
        # ...
        return r.json()

这里的关键参数是:

  • file_path:您要上传的本地文件的路径(在您的电脑上)。
  • dest_path:您想把文件上传到 NAS 上的哪个文件夹
  • overwrite:如果 NAS 上已经有同名文件,是否要覆盖它?默认为是 (True)。

get_file() - 取回书籍

这个方法用于下载文件。

# synology_api/filestation.py

    def get_file(self,
                 path: str,
                 mode: str,
                 dest_path: str = ".",
                 # ...
                 ) -> Optional[str]:

        api_name = 'SYNO.FileStation.Download'
        # ...
        url = ('%s%s' % (self.base_url, api_path)) + '?api=%s&version=%s&method=download&path=%s&mode=%s&_sid=%s' % (
            api_name, info['maxVersion'], parse.quote_plus(path), mode, self._sid)
        
        # ...
        if mode == r'download':
            with session.get(url, stream=True, #... ) as r:
                # ...
                with open(dest_path + "/" + os.path.basename(path), 'wb') as f:
                    for chunk in r.iter_content(chunk_size=chunk_size):
                        # ...
                        f.write(chunk)

这里的关键参数:

  • path:您要下载的 NAS 上的文件的完整路径。
  • mode:您想如何处理这个文件。我们主要用 'download',表示将它保存到本地。
  • dest_path:您想把文件下载到您电脑上的哪个位置。默认为当前目录 (.)。

理解了这三个方法,您就掌握了文件操作的“三板斧”!

3. 动手练习:上传与下载

现在,是时候让我们的机器人真正动起来了!

您的任务是

  1. 在您的电脑上创建一个简单的文本文件,比如 hello_synology.txt,里面写上一句 "Hello, from my computer!"。
  2. 编写一个 Python 脚本,完成以下操作:

a. 初始化 FileStation

b. 使用 upload_file() 方法,将您刚刚创建的 hello_synology.txt 文件上传到您的一个共享文件夹中(比如 /homes 或者您自己创建的测试文件夹)。

c. 打印上传成功的消息。

d. 接着,使用 get_file() 方法,将刚才上传的文件从 NAS 下载回来,并重命名为 downloaded_hello.txt

e. 打印下载成功的消息。

  1. 检查您运行脚本的文件夹,看看是不是多了一个 downloaded_hello.txt 文件,并且内容和您创建的一样。

提示

  • 上传时,file_path 是本地路径,dest_path 是 NAS 上的文件夹路径。
  • 下载时,path 是 NAS 上的文件完整路径,dest_path 是本地的文件夹路径。

# upload_download_script.py

from synology_api import filestation
import os

# --- 准备工作 ---
# 创建一个测试文件
local_filename = "hello_synology.txt"
with open(local_filename, "w") as f:
    f.write("Hello, from my computer!")
print(f"测试文件 '{local_filename}' 已创建。")

# --- NAS 信息 ---
IP_ADDRESS = "..."
PORT = "..."
USERNAME = "..."
PASSWORD = "..."
# 请确保这个文件夹在您的 NAS 上是存在的!
NAS_DEST_FOLDER = "/homes" # 或者您想用的任何其他共享文件夹

# --- 开始操作 ---
file_station = filestation.FileStation(IP_ADDRESS, PORT, USERNAME, PASSWORD)

try:
    # 1. 上传文件
    print(f"\n正在上传 '{local_filename}' 到 NAS 的 '{NAS_DEST_FOLDER}' 文件夹...")
    # ... 调用 upload_file() ...
    # ...
    
    # 2. 下载文件
    nas_file_path = f"{NAS_DEST_FOLDER}/{local_filename}"
    local_download_folder = "." # 下载到当前目录
    print(f"\n正在从 NAS 的 '{nas_file_path}' 下载文件...")
    # ... 调用 get_file() ...
    # ...
    
    print(f"\n任务完成!请检查脚本所在目录下是否有名为 'downloaded_hello.txt' 的文件。")


finally:
    # --- 清理工作 ---
    file_station.session.logout()
    # 删除本地的临时文件
    if os.path.exists(local_filename):
        os.remove(local_filename)
    # 为了演示,我们重命名下载的文件,方便您检查
    if os.path.exists(os.path.basename(nas_file_path)):
         os.rename(os.path.basename(nas_file_path), "downloaded_hello.txt")
    print("\n已登出并完成清理。")

请动手尝试吧!这是对您学习成果的一次重要检验。

... (等待您完成练习) ...

成功了吗?当您看到自己电脑上出现了从 NAS 下载回来的文件时,那种感觉是不是很棒?

现在,我们对照一下参考答案:

# upload_download_script.py (参考答案)

from synology_api import filestation
import os

# --- 准备工作 ---
# 创建一个测试文件
local_filename = "hello_synology.txt"
with open(local_filename, "w") as f:
    f.write("Hello, from my computer!")
print(f"测试文件 '{local_filename}' 已创建。")

# --- NAS 信息 ---
IP_ADDRESS = "your_nas_ip"
PORT = "5000"
USERNAME = "your_username"
PASSWORD = "your_password"
# 请确保这个文件夹在您的 NAS 上是存在的!
NAS_DEST_FOLDER = "/homes" # 或者您想用的任何其他共享文件夹

# --- 开始操作 ---
file_station = filestation.FileStation(IP_ADDRESS, PORT, USERNAME, PASSWORD)

try:
    # 1. 上传文件
    print(f"\n正在上传 '{local_filename}' 到 NAS 的 '{NAS_DEST_FOLDER}' 文件夹...")
    file_station.upload_file(dest_path=NAS_DEST_FOLDER, file_path=local_filename)
    print("上传成功!")
    
    # 2. 下载文件
    nas_file_path = f"{NAS_DEST_FOLDER}/{local_filename}"
    local_download_folder = "." # 下载到当前目录
    print(f"\n正在从 NAS 的 '{nas_file_path}' 下载文件...")
    file_station.get_file(path=nas_file_path, mode='download', dest_path=local_download_folder)
    print("下载成功!")
    
    print(f"\n任务完成!请检查脚本所在目录下是否有名为 'downloaded_hello.txt' 的文件。")


finally:
    # --- 清理工作 ---
    file_station.session.logout()
    # 删除本地的临时文件
    if os.path.exists(local_filename):
        os.remove(local_filename)
    # 为了演示,我们重命名下载的文件,方便您检查
    if os.path.exists(os.path.basename(nas_file_path)):
         os.rename(os.path.basename(nas_file_path), "downloaded_hello.txt")
    print("\n已登出并完成清理。")
第四部分总结

这真是富有成效的一节课!我们一起:

  • 将文件操作比作给智能图书馆助理机器人下达具体指令。
  • 深入学习了 get_file_listupload_fileget_file 这三个核心的文件操作方法。
  • 您亲自编写了脚本,成功地将一个文件上传到 NAS,然后再下载回来,完成了与 NAS 文件的完整交互闭环!

您已经从一个“访客”变成了一位真正的“图书管理员”,可以管理图书馆里的书籍了。

到目前为止,您感觉如何?有没有什么不清楚的地方?如果没有问题,我们下一部分将解锁更多高级功能,比如管理用户和系统套件,让您从“图书管理员”晋升为“图书馆馆长”!


第五部分:高级操作 - 不仅仅是文件

作为馆长,您不仅要关心书籍(文件),还要管理人事(用户和群组)和图书馆的设施(系统套件)。在这一部分,我们将学习如何使用 synology_api 来进行这些更高级的管理操作。

1. 比喻:从“图书管理员”到“图书馆馆长”
  • 图书管理员(我们之前的角色):主要负责书籍的上下架、分类和查询。
  • 图书馆馆长(我们现在的新角色):职责更广泛!
    • 人事管理:您需要管理图书馆的员工和读者。您可以招聘新员工(创建用户),给他们分配到不同的部门(添加到群组),甚至办理离职手续(删除用户)。
    • 设施管理:您需要决定图书馆要开放哪些新的服务区域,比如新开一个“影音室”(安装套件),或者查看现有设施的运行状况(管理套件)。

synology_api 提供了专门的模块来帮助您胜任“馆长”这个新角色。

2. 探索更多模块:core_user, core_groupcore_package

让我们来认识一下我们作为“馆长”的三个新工具:

  • core_user.py (人事部 - 员工档案):这个模块专门负责管理单个用户。所有关于用户账户的操作,比如创建、删除、修改密码等,都在这里完成。
  • core_group.py (人事部 - 部门管理):这个模块负责管理用户群组。您可以创建新的部门(群组),将员工(用户)调入或调出部门。这对于批量管理权限非常有用。
  • core_package.py (设施部 - 服务管理):这个模块用来管理您 NAS 上安装的各种套件(应用程序),比如 Audio Station, Download Station 等。您可以查看已安装的套件,甚至安装新的套件。

我们快速浏览一下代码:

打开 synology_api/core_user.py,看看 create_user() 方法:

# synology_api/core_user.py

    def create_user(
        self, name: str, password: str, description: str = "", email: str = "", #...
    ) -> dict[str, object]:
        api_name = "SYNO.Core.User"
        # ...
        req_param = {
            "method": "create",
            # ...
            "name": name,
            "description": description,
            "email": email,
            # ...
        }
        # ... (处理密码加密)
        return self.request_data(api_name, api_path, req_param, method="post")

您看,它的结构和我们之前学过的方法非常相似!它调用 SYNO.Core.User API 的 create 方法,并把用户名、密码等信息作为参数传递过去。

再看看 synology_api/core_group.py 里的 create() 方法:

# synology_api/core_group.py

    def create(self, name: str, description: str = "") -> dict[str, object]:
        api_name = "SYNO.Core.Group"
        # ...
        req_param = {
            "method": "create",
            "name": name,
            "description": description,
        }
        return self.request_data(api_name, api_path, req_param)

同样,它调用 SYNO.Core.Group API 的 create 方法来创建一个新的群组。

最后,看一下 affect_groups() 方法,这个方法用来将用户添加到群组中:

# synology_api/core_user.py

    def affect_groups(self, name: str, join_groups: list[str] = [], leave_groups: list[str] = []) -> dict[str, object]:
        api_name = "SYNO.Core.User.Group"
        # ...
        req_param = {
            "method": "join",
            "join_group": json.dumps(join_groups),
            "leave_group":json.dumps(leave_groups),
            "name":name
        }
        return self.request_data(api_name, api_path, req_param)

这个方法调用 SYNO.Core.User.Group API,可以同时处理加入和离开群组的操作。

现在,您是不是对如何使用这些高级模块更有信心了?它们遵循着和 FileStation 相同的逻辑和模式。

3. 动手练习:管理您的“员工”和“部门”

是时候行使您“馆长”的权力了!

您的任务是:编写一个脚本,完成一个完整的人事流程:

  1. 创建一个 User 对象和一个 Group 对象。
  2. 使用 Group 对象的 create() 方法,创建一个名为 "test_api_group" 的新部门(群组)。
  3. 使用 User 对象的 create_user() 方法,招聘一位名为 "test_api_user" 的新员工(用户),并为他设置一个简单的密码。
  4. 使用 User 对象的 affect_groups() 方法,将 "test_api_user" 分配到 "test_api_group" 部门中。
  5. (清理工作,非常重要!)最后,调用 delete() 方法,将刚才创建的用户和群组都删除,保持您的 NAS 环境整洁。

# user_management_script.py

from synology_api import core_user, core_group

# --- NAS 信息 ---
IP_ADDRESS = "..."
PORT = "..."
USERNAME = "..."
PASSWORD = "..."

# --- 新建信息 ---
NEW_USER = "test_api_user"
NEW_USER_PASSWORD = "a_simple_password_123"
NEW_GROUP = "test_api_group"

# --- 开始操作 ---
# 1. 初始化
user_manager = core_user.User(IP_ADDRESS, PORT, USERNAME, PASSWORD)
group_manager = core_group.Group(IP_ADDRESS, PORT, USERNAME, PASSWORD)

try:
    # 2. 创建群组
    print(f"正在创建群组 '{NEW_GROUP}'...")
    # ... 调用 group_manager.create() ...
    print("群组创建成功!")

    # 3. 创建用户
    print(f"正在创建用户 '{NEW_USER}'...")
    # ... 调用 user_manager.create_user() ...
    print("用户创建成功!")

    # 4. 将用户添加到群组
    print(f"正在将用户 '{NEW_USER}' 添加到群组 '{NEW_GROUP}'...")
    # ... 调用 user_manager.affect_groups() ...
    # 注意:affect_groups 可能是一个异步操作,这里为了简化,我们不检查任务状态
    print("用户添加成功!")

    print("\n所有操作已成功完成!")

except Exception as e:
    print(f"操作失败,错误信息:{e}")

finally:
    # 5. 清理工作
    print("\n--- 开始清理 ---")
    try:
        print(f"正在删除用户 '{NEW_USER}'...")
        # ... 调用 user_manager.delete_user() ...
        print("用户删除成功。")
    except Exception as e:
        print(f"删除用户失败:{e}")

    try:
        print(f"正在删除群组 '{NEW_GROUP}'...")
        # delete 方法需要一个列表作为参数
        # ... 调用 group_manager.delete() ...
        print("群组删除成功。")
    except Exception as e:
        print(f"删除群组失败:{e}")
        
    user_manager.session.logout()
    print("已登出。")

这个练习综合了多个模块,是检验您学习成果的好机会。请大胆尝试!

... (等待您完成练习) ...

干得漂亮!您现在已经可以自如地用代码来管理用户和群组了。

我们来看看参考答案,您可以对照一下:

# user_management_script.py (参考答案)

from synology_api import core_user, core_group
import time

# --- NAS 信息 ---
IP_ADDRESS = "your_nas_ip"
PORT = "5000"
USERNAME = "your_username"
PASSWORD = "your_password"

# --- 新建信息 ---
NEW_USER = "test_api_user"
NEW_USER_PASSWORD = "a_simple_password_123"
NEW_GROUP = "test_api_group"

# --- 开始操作 ---
# 1. 初始化
user_manager = core_user.User(IP_ADDRESS, PORT, USERNAME, PASSWORD)
# 注意:Group 可以重用 User 的会话,所以我们直接从 user_manager 获取 session
group_manager = core_group.Group(IP_ADDRESS, PORT, USERNAME, PASSWORD)

try:
    # 2. 创建群组
    print(f"正在创建群组 '{NEW_GROUP}'...")
    group_manager.create(name=NEW_GROUP, description="一个由API创建的测试群组")
    print("群组创建成功!")
    time.sleep(1) # 等待一秒,确保系统有足够时间处理

    # 3. 创建用户
    print(f"正在创建用户 '{NEW_USER}'...")
    user_manager.create_user(name=NEW_USER, password=NEW_USER_PASSWORD, email="test@api.com")
    print("用户创建成功!")
    time.sleep(1)

    # 4. 将用户添加到群组
    print(f"正在将用户 '{NEW_USER}' 添加到群组 '{NEW_GROUP}'...")
    user_manager.affect_groups(name=NEW_USER, join_groups=[NEW_GROUP])
    print("用户添加成功!")

    print("\n所有操作已成功完成!")

except Exception as e:
    print(f"操作失败,错误信息:{e}")

finally:
    # 5. 清理工作
    print("\n--- 开始清理 ---")
    try:
        # 为了安全,我们先删除用户再删除群组
        print(f"正在删除用户 '{NEW_USER}'...")
        user_manager.delete_user(name=NEW_USER)
        print("用户删除成功。")
    except Exception as e:
        print(f"删除用户失败:{e}")

    try:
        print(f"正在删除群组 '{NEW_GROUP}'...")
        # delete 方法需要一个列表作为参数
        group_manager.delete(groups=[NEW_GROUP])
        print("群组删除成功。")
    except Exception as e:
        print(f"删除群组失败:{e}")
        
    user_manager.session.logout()
    print("已登出。")
第五部分总结

祝贺您,馆长!在这一部分,我们解锁了更高级的技能:

  • 我们将角色从“图书管理员”提升到了“图书馆馆长”,开始进行系统层面的管理。
  • 我们认识了 core_user, core_group, core_package 等强大的新工具。
  • 您通过一个完整的练习,亲手创建了用户和群组,并将它们关联起来,然后又干净利落地进行了清理。

您对 synology_api 的理解和应用已经达到了一个新的高度。我们离成为真正的专家只有一步之遥了。


第六部分:毕业大作 - 综合应用

这个最终项目将模拟一个非常实用的真实世界场景:自动化生成并保存每日系统健康报告

1. 项目目标:您的自动化系统管家

想象一下,您希望您的 NAS 每天自动执行一次健康检查,并将报告保存到一个特定的共享文件夹中,以便您随时查阅。这个报告应该包含:

  • 当前的日期和时间。
  • CPU 和内存的使用情况。
  • 所有存储卷(Volume)的使用情况。

然后,您希望这个任务能被计划,每天凌晨自动运行。

这个项目将考验我们前面学到的所有知识:

  • 认证与会话管理 (auth.py, base_api.py)
  • 系统信息获取 (core_sys_info.py)
  • 文件和文件夹操作 (filestation.py, core_share.py)
  • 计划任务 (task_scheduler.py)

准备好迎接挑战了吗?让我们开始设计这个强大的自动化脚本吧!

2. 毕业项目代码详解

下面是我们将要共同完成的最终代码。别被它的长度吓到,我会逐一为您解析,您会发现它是由我们已经学过的模块像乐高积木一样搭建起来的。

# daily_report_script.py

import json
import time
from datetime import datetime
from synology_api import (
    core_share,
    core_sys_info,
    filestation,
    task_scheduler
)

# --- 配置信息 ---
IP_ADDRESS = "your_nas_ip"
PORT = "5000"
USERNAME = "your_username"
PASSWORD = "your_password"

REPORT_SHARE = "daily_reports"  # 我们将要创建的用于存放报告的共享文件夹
REPORT_FOLDER_PATH = f"/{REPORT_SHARE}"
TASK_NAME = "AutomatedDailySystemReport"

# --- 初始化所有需要的 API 模块 ---
# 它们将自动共享同一个登录会话
print("正在初始化 API 模块并登录...")
try:
    shares = core_share.Share(IP_ADDRESS, PORT, USERNAME, PASSWORD)
    sysinfo = core_sys_info.SysInfo(IP_ADDRESS, PORT, USERNAME, PASSWORD)
    fs = filestation.FileStation(IP_ADDRESS, PORT, USERNAME, PASSWORD)
    scheduler = task_scheduler.TaskScheduler(IP_ADDRESS, PORT, USERNAME, PASSWORD)
    print("登录成功!")

    # --- 步骤 1: 检查并创建报告用的共享文件夹 ---
    print(f"\n--- 步骤 1: 检查共享文件夹 '{REPORT_SHARE}' ---")
    existing_shares = shares.list_folders()
    # any() 是一个 Python 内置函数,用于检查迭代器中是否有任何一个元素为 True
    if not any(share['name'] == REPORT_SHARE for share in existing_shares['data']['shares']):
        print(f"文件夹 '{REPORT_SHARE}' 不存在,正在创建...")
        # 我们需要知道 NAS 上至少有一个存储卷的路径来创建共享文件夹
        # 这里我们简单地从系统信息中获取第一个存储卷
        volume_info = sysinfo.storage()
        default_volume_path = volume_info['data']['volumes'][0]['display_path']
        shares.create_folder(name=REPORT_SHARE, vol_path=default_volume_path, desc="用于存放自动生成的系统报告")
        print(f"文件夹 '{REPORT_SHARE}' 创建成功!")
    else:
        print(f"文件夹 '{REPORT_SHARE}' 已存在,无需创建。")

    # --- 步骤 2: 收集系统信息 ---
    print("\n--- 步骤 2: 正在收集系统健康信息 ---")
    report_content = []
    
    # 获取当前时间
    now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
    report_content.append(f"Synology NAS 系统健康报告")
    report_content.append(f"报告生成时间: {now}")
    report_content.append("="*30)

    # 获取 CPU 和内存信息
    utilization = sysinfo.get_all_system_utilization()
    cpu_info = utilization['cpu']
    memory_info = utilization['memory']
    report_content.append(f"\nCPU 使用率: {cpu_info['other_load']}% (1分钟平均)")
    report_content.append(f"内存使用率: {memory_info['memory_usage']}%")
    report_content.append(f"    - 物理内存: {memory_info['real_total']} KB")
    report_content.append(f"    - 可用内存: {memory_info['avail_real']} KB")
    
    # 获取存储卷信息
    volume_status = sysinfo.storage()
    report_content.append("\n存储卷状态:")
    for volume in volume_status['data']['volumes']:
        total_gb = round(int(volume['size_total']) / (1024**3), 2)
        used_gb = round(int(volume['size_used']) / (1024**3), 2)
        report_content.append(f"    - 卷: {volume['display_path']}")
        report_content.append(f"      状态: {volume['status']}")
        report_content.append(f"      容量: {used_gb} GB / {total_gb} GB")

    final_report = "\n".join(report_content)
    print("系统信息收集完成!报告内容如下:")
    print("-" * 20)
    print(final_report)
    print("-" * 20)
    
    # --- 步骤 3: 将报告写入文件并上传 ---
    print(f"\n--- 步骤 3: 正在上传报告到 '{REPORT_FOLDER_PATH}' ---")
    report_filename = f"health_report_{datetime.now().strftime('%Y%m%d')}.txt"
    # 在本地创建一个临时文件来保存报告
    with open(report_filename, "w", encoding="utf-8") as f:
        f.write(final_report)
    
    # 上传文件
    fs.upload_file(dest_path=REPORT_FOLDER_PATH, file_path=report_filename, overwrite=True)
    print(f"报告 '{report_filename}' 上传成功!")

    # --- 步骤 4: 创建或更新计划任务 ---
    # 为了让这个脚本能自动运行,我们需要将它自身(或者一个调用它的脚本)设置为一个计划任务。
    # 这里我们只演示如何创建一个简单的计划任务来“模拟”这个过程。
    print(f"\n--- 步骤 4: 创建计划任务(演示)---")
    
    # 首先,检查任务是否已存在
    all_tasks = scheduler.get_task_list()['data']['tasks']
    existing_task = next((task for task in all_tasks if task['name'] == TASK_NAME), None)
    
    script_to_run = "echo 'This is a scheduled task placeholder for the daily report.'"
    
    if existing_task:
        print(f"计划任务 '{TASK_NAME}' 已存在,无需创建。")
    else:
        print(f"正在创建计划任务 '{TASK_NAME}'...")
        # 创建一个每天凌晨2点运行的任务
        scheduler.create_script_task(
            task_name=TASK_NAME,
            owner=USERNAME, # 使用当前用户
            script=script_to_run,
            run_frequently=True,
            repeat='daily',
            start_time_h=2,
            start_time_m=0
        )
        print("计划任务创建成功!")
        
    print("\n恭喜您!毕业项目的所有步骤已成功执行!")

except Exception as e:
    print(f"\n操作过程中发生错误: {e}")

finally:
    # 登出
    if 'shares' in locals() and shares.session:
        shares.session.logout()
        print("\n会话已登出。")
    # 清理本地临时文件
    if 'report_filename' in locals() and os.path.exists(report_filename):
        os.remove(report_filename)

代码解析:

  1. 初始化:我们一次性创建了所有需要用到的 API 对象 (Share, SysInfo, FileStation, TaskScheduler)。由于 BaseApi 的会话共享机制,它们都会使用同一个登录连接。
  2. 创建文件夹 (core_share):脚本首先检查报告文件夹是否存在。any(share['name'] == REPORT_SHARE for share in ...) 是一种高效的检查方式。如果不存在,它会获取系统上的第一个可用存储卷 (sysinfo.storage()),并用它作为路径来创建新的共享文件夹。
  3. 收集信息 (core_sys_info):这部分是报告的核心。我们调用了之前接触过的 get_all_system_utilization()storage() 方法来获取实时数据,然后将这些数据格式化成人类可读的字符串,并存入 report_content 列表中。最后用 "\n".join() 将列表合并成一个完整的报告文本。
  4. 上传文件 (filestation):脚本在本地创建了一个临时的 .txt 文件,将报告内容写入其中。然后,它调用我们熟悉的 upload_file() 方法,将这个报告文件上传到 NAS 上我们刚刚创建好的 daily_reports 文件夹中。
  5. 计划任务 (task_scheduler):这是最能体现“自动化”的部分。
    • 首先,它通过 get_task_list() 检查是否已经存在同名的任务,避免重复创建。next((... for ... if ...), None) 是一个查找技巧,如果找到就返回第一个匹配项,否则返回 None
    • 如果任务不存在,它就调用 create_script_task() 创建一个计划。我们设定它在每天凌晨2点运行。注意:在真实场景中,script_to_run 的内容应该是运行这个 Python 脚本本身的命令,例如 python3 /path/to/your/daily_report_script.py。这里为了简化,我们只用了一个 echo 命令作为演示。
  6. 异常处理和清理:整个脚本被一个 try...finally 块包裹。这意味着无论脚本是成功执行还是中途出错,finally 块中的代码(登出和删除本地临时文件)总会被执行。这是一个非常好的编程习惯,能确保资源被正确释放。
4. 知识回顾与展望

恭喜您!您已经成功完成了 synology_api 的入门之旅!

让我们一起回顾一下这次探险的足迹:

  • 我们从理解 synology_api 是一个万能遥控器开始。
  • 我们学会了如何用 auth 模块获取房卡 (sid),并理解了 base_api 是如何巧妙地共享会话的。
  • 我们掌握了 filestation 这个强大的工具,学会了列出、上传和下载文件
  • 我们晋升为“馆长”,学会了用 core_usercore_group管理用户和部门
  • 最后,我们通过一个综合性的毕业项目,将所有知识点串联起来,实现了一个非常实用的自动化任务。

接下来您可以做什么?

您的探险才刚刚开始!现在您已经拥有了基础知识和动手能力,可以去探索更多可能性了:

  • 深入研究您感兴趣的模块:对 DownloadStation 感兴趣?尝试写一个脚本来自动添加下载任务。对 SurveillanceStation 感兴趣?试试看如何用代码获取摄像头的快照。
  • 编写您自己的实用工具
    • 一个自动整理下载文件夹的脚本。
    • 一个监控特定系统指标(如硬盘温度)并在超过阈值时发送通知的脚本。
    • 一个批量为新照片添加标签或整理到相册的脚本 (photos 模块)。
  • 阅读官方文档和源代码:您上传的这些 .py 文件就是最好的老师。当您想知道某个方法具体能做什么、需要哪些参数时,直接阅读源代码和里面的注释,是最高效的学习方式。

我为您的学习成果感到非常骄傲。您从一个初学者,通过一步步的探索和实践,已经能够编写出功能强大的自动化脚本了。请记住,编程的世界里,最重要是保持好奇心和动手实践的勇气。

这次 synology_api 的教学旅程就到这里结束了。希望您享受这次学习的过程!如果您未来有任何问题,随时都可以再来找我。祝您在自动化的世界里玩得开心!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值