麒麟 V10系统中离线安装python的setuptools和pip,并使用python代码查询达梦数据库,并上传文件到minio

麒麟 V10系统中默认安装了python3.7版本,但是没有安装pip命令

1.python 环境安装

	1.下载Python版本对用的 setuptools和pip版本 源码包
	下载地址:
		setuptools:https://pypi.org/project/setuptools/#files(选择.tar.gz或.whl)
		pip:https://pypi.org/project/pip/#files(选择.tar.gz或.whl)
	建议下载最新版本的.tar.gz源码包(兼容性更好)
	2.将下载的setuptools-xxx.tar.gz和pip-xxx.tar.gz通过 U 盘、共享文件夹等方式拷贝到麒麟 V10 系统中(如/root/offline_packages目录)
	3.安装 setuptools(pip 依赖)
		# 进入安装包目录
		cd /root/offline_packages
		
		# 解压setuptools
		tar -zxvf setuptools-xxx.tar.gz
		cd setuptools-xxx
		
		# 用系统自带的python3安装
		python3 setup.py install
	4.安装 pip
		# 返回安装包目录
		cd ..
		
		# 解压pip
		tar -zxvf pip-xxx.tar.gz
		cd pip-xxx
		
		# 安装pip
		python3 setup.py install
	5.验证安装
		pip3 --version  # 或 pip --version(若系统默认指向python3)

  2.dmPython和minio包的离线安装

	1.在有网络的机器上下载包
		# 创建存储目录
		mkdir offline_packages
		
		# 下载dmPython及其依赖
		pip download dmPython -d ./offline_packages
		
		# 下载minio及其依赖
		pip download minio -d ./offline_packages
	2.将包拷贝到目标机器
		通过 U 盘、移动硬盘或其他方式,将offline_packages目录拷贝到需要离线安装的机器上。
	3.在目标机器上进行离线安装
		# 安装dmPython
		pip install --no-index --find-links=./offline_packages dmPython
		
		# 安装minio
		pip install --no-index --find-links=./offline_packages minio	

  3.python代码

# -*- coding: utf-8 -*-

"""将达梦数据库中的文件上传到 MinIO 并按要求处理。

依赖:
    pip install dmPython minio

运行示例:
    python scripts/upload_dm_to_minio.py
"""

from __future__ import annotations

import logging
import os
import sys
from contextlib import closing
from datetime import datetime
from pathlib import Path
from typing import Iterator, Tuple

try:
    import dmPython  # type: ignore
except ModuleNotFoundError as exc:  # pragma: no cover
    raise SystemExit(
        "未找到 dmPython 库,请先使用 `pip install dmPython` 安装后再运行此脚本"
    ) from exc

from minio import Minio
from minio.error import S3Error


# --------------------------- 配置区 --------------------------- #
DM_HOST = "127.0.0.1"
DM_PORT = 5237
DM_USER = "SYSDBA"
DM_PASSWORD = "SYSDBA001"
DM_SCHEMA = "TEST_SCHEMA"
DM_TABLE = "t_files"
DM_FIELD_ROWGUID = "ROW_GUID"
DM_FIELD_FILEPATH = "FILE_PATH"

MINIO_ENDPOINT = "127.0.0.1:9000"
MINIO_ACCESS_KEY = "admin"
MINIO_SECRET_KEY = "admin"
MINIO_BUCKET = "test"
MINIO_SECURE = False  # MinIO 默认为 http

BASE_DIR = Path("/data")

LOG_FILE = Path(__file__).with_name("upload_failures.log")


# --------------------------- 日志配置 --------------------------- #
LOG_FILE.parent.mkdir(parents=True, exist_ok=True)
file_handler = logging.FileHandler(LOG_FILE, encoding="utf-8")
file_handler.setLevel(logging.ERROR)

console_handler = logging.StreamHandler(sys.stdout)
console_handler.setLevel(logging.INFO)

logging.basicConfig(
    level=logging.INFO,
    format="%(asctime)s [%(levelname)s] %(message)s",
    handlers=[file_handler, console_handler],
)

logger = logging.getLogger(__name__)


# --------------------------- 数据库相关 --------------------------- #
def iter_attachments() -> Iterator[Tuple[str, str]]:
    """从达梦数据库读取 rowGuid 和 filePath。"""

    conn = dmPython.connect(
        user=DM_USER,
        password=DM_PASSWORD,
        server=DM_HOST,
        port=DM_PORT,
    )

    with closing(conn):
        with closing(conn.cursor()) as cursor:
            cursor.execute(
                f"SELECT {DM_FIELD_ROWGUID}, {DM_FIELD_FILEPATH} "
                f"FROM {DM_SCHEMA}.{DM_TABLE} "
                f"WHERE {DM_FIELD_ROWGUID} IS NOT NULL AND {DM_FIELD_FILEPATH} IS NOT NULL"
            )
            while True:
                row = cursor.fetchone()
                if row is None:
                    break
                yield row[0], row[1]


# --------------------------- MinIO 相关 --------------------------- #
def ensure_bucket_exists(client: Minio, bucket_name: str) -> None:
    if not client.bucket_exists(bucket_name):
        client.make_bucket(bucket_name)


def build_object_name(row_guid: str, source_path: Path) -> str:
    suffix = source_path.suffix
    if not suffix:
        return row_guid
    return f"{row_guid}{suffix}"


def upload_one_file(client: Minio, bucket: str, row_guid: str, file_path: Path) -> None:
    object_name = build_object_name(row_guid, file_path)
    client.fput_object(bucket, object_name, file_path.as_posix())
    logger.info("上传成功:%s -> %s/%s", file_path, bucket, object_name)


def log_failure(file_path: Path, exc: Exception) -> None:
    size = file_path.stat().st_size if file_path.exists() else -1
    logger.error(
        "上传失败 | 路径: %s | 时间: %s | 大小: %s | 错误: %s",
        file_path,
        datetime.now().isoformat(timespec="seconds"),
        size,
        exc,
    )


# --------------------------- 主流程 --------------------------- #
def main() -> None:
    client = Minio(
        MINIO_ENDPOINT,
        access_key=MINIO_ACCESS_KEY,
        secret_key=MINIO_SECRET_KEY,
        secure=MINIO_SECURE,
    )

    ensure_bucket_exists(client, MINIO_BUCKET)

    processed = 0
    failed = 0

    for row_guid, file_path_value in iter_attachments():
        relative_path = file_path_value.lstrip("/\\")
        full_path = (BASE_DIR / relative_path).resolve()

        if not full_path.exists():
            log_failure(full_path, FileNotFoundError("文件不存在"))
            failed += 1
            continue

        try:
            upload_one_file(client, MINIO_BUCKET, row_guid, full_path)
        except (FileNotFoundError, S3Error, OSError) as exc:
            log_failure(full_path, exc)
            failed += 1
            continue

        try:
            full_path.unlink()
            logger.info("已删除本地文件:%s", full_path)
        except OSError as exc:
            logger.warning("文件删除失败:%s,错误:%s", full_path, exc)

        processed += 1

    logger.info("处理完成,总计:%s,失败:%s", processed + failed, failed)


if __name__ == "__main__":
    try:
        main()
    except Exception as exc:  # pragma: no cover
        logger.exception("脚本运行异常: %s", exc)
        sys.exit(1)

  

posted @ 2025-10-31 21:33  东峰叵,com  阅读(599)  评论(0)    收藏  举报