监听SHP目录自动注册SuperMap iServer地图服务(Windows版)

一、项目背景

在GIS项目中,我们经常需要将Shapefile数据发布为地图服务。传统方式需要手动登录iServer管理界面,创建Provider和Component,操作繁琐且容易出错。

本文介绍如何使用Python实现监听指定目录,当检测到新的SHP目录时自动注册到SuperMap iServer的自动化工具。

二、功能特性

功能 说明
📂 目录监听 使用watchdog库实时监控目录变化
📄 智能检测 自动检测目录是否包含SHP文件,避免误注册
⏱️ 上传等待 等待文件上传完成(静默N秒)后再注册
📊 状态记录 JSON格式注册表,记录检索时间、发布时间、状态
🔄 启动扫描 服务启动时自动扫描已有目录并注册
🖥️ 窗口控制 支持前台显示窗口/后台无窗口运行
🚀 开机自启 支持注册为Windows开机自启服务
📦 一键打包 提供PowerShell脚本打包为exe可执行文件

三、技术栈

  • Python 3.8+:主开发语言
  • watchdog:文件系统监听库
  • requests:HTTP请求库(调用iServer REST API)
  • PyInstaller:打包工具
  • SuperMap iServer REST API:服务注册接口

四、核心实现

4.1 目录监听

使用watchdog库监听目录创建事件:

python 复制代码
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler

class ShpDirectoryHandler(FileSystemEventHandler):
    def on_created(self, event):
        if not event.is_directory:
            return
        dir_path = event.src_path
        if os.path.isdir(dir_path):
            time.sleep(1)  # 防止重复触发
            register_directory(dir_path)

# 启动监听器
observer = Observer()
observer.schedule(event_handler, watch_dir, recursive=False)
observer.start()

4.2 SHP文件检测

注册前检查目录是否包含.shp文件:

python 复制代码
def has_shp_files(dir_path):
    """检查目录是否包含shp文件"""
    for root, dirs, files in os.walk(dir_path):
        for file in files:
            if file.lower().endswith('.shp'):
                return True
    return False

4.3 等待文件上传完成

实现静默等待机制,确保文件上传完成:

python 复制代码
def wait_for_stable(dir_path, stable_sec, max_wait_sec):
    """等待目录文件上传完成"""
    elapsed = 0
    last_modify_time = 0
    
    while elapsed < max_wait_sec:
        current_max_modify = 0
        for root, dirs, files in os.walk(dir_path):
            for file in files:
                mtime = os.path.getmtime(os.path.join(root, file))
                if mtime > current_max_modify:
                    current_max_modify = mtime
        
        if current_max_modify == last_modify_time:
            # 静默期内无文件修改,认为上传完成
            return True
        
        last_modify_time = current_max_modify
        elapsed += stable_sec
        time.sleep(stable_sec)
    
    return True  # 超时强制继续

4.4 iServer服务注册

调用iServer REST API注册Provider和Component:

python 复制代码
def register_provider(dir_path):
    """注册Provider"""
    provider_name = f"shapefileMap-{os.path.basename(dir_path)}"
    url = f"{iserver_host}/iserver/manager/providers.json?token={token}"
    
    payload = {
        "config": {
            "shpDir": dir_path,
            "charset": "GBK",
            "stylePath": "",
            "cacheEnabled": False
        },
        "name": provider_name,
        "type": "com.supermap.services.providers.ShapeFileMapProvider"
    }
    
    response = requests.post(url, json=payload)
    return provider_name if response.status_code in range(200, 300) else None

def register_component(provider_name, dir_path):
    """注册Component"""
    component_name = f"map-shapefile-{os.path.basename(dir_path)}"
    url = f"{iserver_host}/iserver/manager/components.json?token={token}"
    
    payload = {
        "interfaceNames": "rest",
        "name": component_name,
        "providers": provider_name,
        "config": {
            "outputPath": "",
            "outputSite": "",
            "logLevel": "info"
        },
        "type": "com.supermap.services.components.impl.MapImpl"
    }
    
    response = requests.post(url, json=payload)
    return component_name if response.status_code in range(200, 300) else None

4.5 注册状态记录

使用JSON文件记录每个目录的注册状态:

python 复制代码
def update_registry(dir_path, status, retrieve_time=None, publish_time=None, error_msg=None):
    """更新注册表记录"""
    registry = load_registry()
    
    record = registry.get(dir_path, {})
    if retrieve_time:
        record['retrieve_time'] = retrieve_time
    if publish_time:
        record['publish_time'] = publish_time
    record['status'] = status
    record['dir_path'] = dir_path
    record['dir_name'] = os.path.basename(dir_path)
    if error_msg:
        record['error_message'] = error_msg
    
    registry[dir_path] = record
    save_registry(registry)

注册表示例(registry.json):

json 复制代码
{
  "D:\\data\\shp\\cities": {
    "retrieve_time": "2026-07-24T10:00:00.000000",
    "publish_time": "2026-07-24T10:00:15.000000",
    "status": "success",
    "dir_path": "D:\\data\\shp\\cities",
    "dir_name": "cities"
  }
}

状态说明:

  • pending:目录已检测到,等待注册
  • skipped:目录不包含SHP文件,跳过
  • success:注册成功
  • failed:注册失败

五、项目结构

复制代码
shp_watcher/
├── watch_shp.py          # 主程序
├── config.ini            # 配置文件
├── build.ps1             # 打包脚本
├── startup.bat           # 前台启动脚本
├── startup_background.bat # 后台启动脚本
└── dist/                 # 打包输出目录
    ├── shp_watcher.exe   # 可执行文件
    ├── config.ini        # 配置文件
    └── registry.json     # 注册表(自动生成)

六、配置文件说明

config.ini配置项:

ini 复制代码
[iServer]
host = http://172.16.12.27:8090   # iServer服务地址
token = your_token_here           # 管理Token
charset = GBK                     # SHP字符集
style_path =                      # 样式文件路径(可选)
cache_enabled = false             # 是否启用缓存

[Watcher]
watch_dir = D:\data\shp           # 监听目录(必须绝对路径!)
stable_seconds = 5                # 静默判定时间(秒)
max_wait_seconds = 300            # 最大等待时间(秒)

[System]
background = false                # 是否后台运行
auto_start = false                # 是否开机自启

⚠️ 注意watch_dir必须设置为绝对路径

七、使用方法

7.1 获取iServer Token

登录iServer管理界面 → 令牌 → 生成Token

7.2 运行方式

bash 复制代码
# 方式1:直接运行exe(前台模式,显示窗口)
shp_watcher.exe

# 方式2:前台模式(通过bat脚本)
startup.bat

# 方式3:后台模式(无窗口)
startup_background.bat
shp_watcher.exe --background

# 方式4:安装开机自启
shp_watcher.exe --install

# 方式5:卸载开机自启
shp_watcher.exe --uninstall

7.3 打包为exe

powershell 复制代码
powershell -ExecutionPolicy Bypass -File build.ps1

打包脚本会自动:

  1. 检查Python环境
  2. 安装依赖包(watchdog, requests, pyinstaller)
  3. 执行PyInstaller打包
  4. 复制配置文件和启动脚本

八、运行流程

复制代码
启动服务
    │
    ├── 加载配置文件
    ├── 加载注册表记录
    ├── 扫描已有目录
    │       │
    │       ├── 包含SHP文件?
    │       │       ├── 是 → 更新检索时间 → 等待稳定 → 注册Provider → 注册Component → 更新状态
    │       │       └── 否 → 跳过
    │       │
    └── 启动目录监听器
            │
            ├── 检测到新目录创建
            │       │
            │       ├── 包含SHP文件?
            │       │       ├── 是 → 更新检索时间 → 等待稳定 → 注册Provider → 注册Component → 更新状态
            │       │       └── 否 → 跳过
            │       │
            └── 持续监听...

九、注意事项

  1. 监听目录必须是绝对路径 :如 D:\data\shp/mnt/data/shp
  2. iServer Token有效期:建议设置较长有效期或定期更新
  3. 开机自启需要管理员权限:首次安装时会自动提升权限
  4. 日志文件 :默认生成在exe同级目录的 iserver_register.log
  5. 注册表文件 :默认生成在exe同级目录的 registry.json
  6. 后台运行 :可通过 --background 参数或 startup_background.bat 实现

十、总结

本工具实现了从SHP目录检测到iServer服务注册的全流程自动化,主要优势:

  1. 节省人力:无需手动登录iServer管理界面
  2. 及时响应:新目录创建后自动触发注册
  3. 避免错误:智能检测SHP文件,避免误注册
  4. 状态追踪:注册表记录便于追溯和排查问题
  5. 灵活部署:支持前台/后台运行,支持开机自启
  6. 跨平台兼容:核心逻辑可移植到Linux环境

完整代码GitHub仓库

如果觉得本文对你有帮助,欢迎点赞、收藏、评论!如有问题,欢迎留言讨论。

相关推荐
程序员老陆2 小时前
FFmpeg6 在 Windows 打开麦克风并录成 PCM:不走 Qt Multimedia,也不碰 WASAPI
windows·ffmpeg·音视频·pcm
chushiyunen2 小时前
神雕武功排名
windows
酩酊仙人3 小时前
Windows Server部署django
windows·django·sqlite
蓝斯49717 小时前
从.到实现一个Windows上的虚拟hid键盘设备
windows·单片机·计算机外设
CODER030421 小时前
封装忽律底层硬件差异的自定义系统
windows·microsoft
软件资深者1 天前
Windows10、11轻松设置 使用教程:把Windows繁杂的设置集成到一个面板,关广告/关更新/调隐私全搞定,系统设置工具新手 5 分钟上手(2026)
windows
脚踏实地皮皮晨1 天前
003005002_WPF StackPanel 基类官方类定义逐行深度解析
开发语言·windows·算法·c#·wpf·visual studio
YCOSA20251 天前
Windows 11 Insider 实验预览版 26300.9032 基于26100.6(检查点26100.1746)
windows
happymagic1 天前
vmware workstation Pro 虚拟机设定启停的时间段
运维·服务器·windows