Python 连接星辰天合(XSKY)存储解决方案

一、理解星辰天合(XSKY)存储系统

星辰天合(XSKY)提供企业级分布式存储解决方案,支持对象存储、块存储和文件存储服务。Python 可以通过 SDK 或 REST API 与 XSKY 存储系统交互,实现数据管理、监控和自动化操作。

二、安装必要的python库

这里使用boto3的S3协议,主要任务是链接星辰天合,然后从桶的文件夹中获取图片文件到本地处理。所以这里需要安装boto3库:

pip install boto3
 

三、常用操作代码示例

import boto3
class XSkyStorageViewer:
    def __init__(self, endpoint, access_key, secret_key, bucket_name):
        """
        初始化XSKY存储桶查看器

        Args:
            endpoint (str): XSKY存储服务的端点URL
            access_key (str): 访问密钥
            secret_key (str): 秘密密钥
            bucket_name (str): 存储桶名称
        """
        self.endpoint = endpoint
        self.access_key = access_key
        self.secret_key = secret_key
        self.bucket_name = bucket_name
        self.client = None

    def connect(self):
        """使用S3协议连接到XSKY存储服务"""
        try:
            self.client = boto3.client(
                's3',
                endpoint_url=self.endpoint,
                aws_access_key_id=self.access_key,
                aws_secret_access_key=self.secret_key,
                config=boto3.session.Config(signature_version='s3v4')
            )
            # 验证连接
            self.client.list_buckets()
            logger.info(f"成功连接到存储服务: {self.endpoint}")
        except ClientError as e:
            logger.error(f"连接失败: {e.response['Error']['Message']}")
            raise
        except Exception as e:
            logger.error(f"连接失败: {str(e)}")
            raise

    def list_images(self, folder_path):
        """
        列出指定文件夹中的所有图片文件

        Args:
            folder_path (str): 文件夹路径,应包含末尾的斜杠

        Returns:
            list: 图片文件的键名列表
        """
        if not self.client:
            raise Exception("请先连接到存储服务")

        # 确保文件夹路径以斜杠结尾
        if not folder_path.endswith('/'):
            folder_path += '/'

        try:
            # 获取存储桶中指定文件夹下的所有对象
            paginator = self.client.get_paginator('list_objects_v2')
            pages = paginator.paginate(
                Bucket=self.bucket_name,
                Prefix=folder_path
            )

            # 过滤出图片文件
            image_extensions = ['.jpg', '.jpeg', '.png', '.gif', '.bmp']
            image_objects = []

            for page in pages:
                if 'Contents' in page:
                    for obj in page['Contents']:
                        if any(obj['Key'].lower().endswith(ext) for ext in image_extensions):
                            image_objects.append(obj['Key'])

            logger.info(f"在 {folder_path} 下找到 {len(image_objects)} 张图片")
            return image_objects

        except ClientError as e:
            logger.error(f"列出图片失败: {e.response['Error']['Message']}")
            raise
        except Exception as e:
            logger.error(f"列出图片失败: {str(e)}")
            raise

    def display_image(self, image_key):
        """
        从S3读取图片并使用OpenCV显示

        Args:
            image_key (str): 图片在存储桶中的键名
        """
        if not self.client:
            raise Exception("请先连接到存储服务")
        try:
            # 从S3下载图片
            response = self.client.get_object(
                Bucket=self.bucket_name,
                Key=image_key
            )

            # 读取图片内容
            image_content = response['Body'].read()

            # 将字节流转换为OpenCV图像
            nparr = np.frombuffer(image_content, np.uint8)
            image = cv2.imdecode(nparr, cv2.IMREAD_COLOR)

            if image is None:
                logger.error(f"无法解码图片: {image_key}")
                return

            # 显示图片
            # window_name = os.path.basename(image_key)
            # cv2.imshow(window_name, image)
            # logger.info(f"正在显示图片: {image_key}")
            #
            # # 等待按键关闭窗口
            # cv2.waitKey(0)
            # cv2.destroyAllWindows()

        except ClientError as e:
            logger.error(f"获取图片失败: {e.response['Error']['Message']}")
            raise
        except Exception as e:
            logger.error(f"显示图片失败: {str(e)}")
            raise
        return image
    def list_subfolders(self, parent_folder):
        """
        列出指定文件夹中的所有子文件夹
        Args:
            parent_folder (str): 父文件夹路径,应包含末尾的斜杠
        Returns:
            list: 子文件夹名称列表
        """
        if not self.client:
            raise Exception("请先连接到存储服务")
        # 确保父文件夹路径以斜杠结尾
        if not parent_folder.endswith('/'):
            parent_folder += '/'
        try:
            # 使用delimiter='/'来获取子文件夹
            paginator = self.client.get_paginator('list_objects_v2')
            pages = paginator.paginate(
                Bucket=self.bucket_name,
                Prefix=parent_folder,
                Delimiter='/'
            )
            subfolders = []
            for page in pages:
                if 'CommonPrefixes' in page:
                    for prefix in page['CommonPrefixes']:
                        # 提取子文件夹名称(去掉父路径和末尾斜杠)
                        subfolder = prefix['Prefix'][len(parent_folder):-1]
                        subfolder=os.path.join(parent_folder, subfolder)
                        subfolders.append(subfolder)
            #logger.info(f"在 {parent_folder} 下找到 {len(subfolders)} 个子文件夹")
            return subfolders
        except ClientError as e:
            logger.error(f"列出子文件夹失败: {e.response['Error']['Message']}")
            raise
        except Exception as e:
            logger.error(f"列出子文件夹失败: {str(e)}")
            raise
    def list_subfolders_(self, parent_folder):
        """
        列出指定文件夹中的所有最后一层子文件夹的全路径

        Args:
            parent_folder (str): 父文件夹路径,应包含末尾的斜杠

        Returns:
            list: 最后一层子文件夹的全路径列表
        """
        if not self.client:
            raise Exception("请先连接到存储服务")

        # 确保父文件夹路径以斜杠结尾
        if not parent_folder.endswith('/'):
            parent_folder += '/'

        # 存储所有最后一层子文件夹
        leaf_folders = []

        # 使用栈来进行深度优先搜索
        stack = [parent_folder]

        while stack:
            current_folder = stack.pop()

            try:
                # 获取当前文件夹的直接子文件夹
                paginator = self.client.get_paginator('list_objects_v2')
                pages = paginator.paginate(
                    Bucket=self.bucket_name,
                    Prefix=current_folder,
                    Delimiter='/'
                )

                subfolders = []
                for page in pages:
                    if 'CommonPrefixes' in page:
                        for prefix in page['CommonPrefixes']:
                            subfolders.append(prefix['Prefix'])

                # 如果没有子文件夹,说明是最后一层
                if not subfolders:
                    # 排除父文件夹本身
                    if current_folder != parent_folder:
                        #print(type(current_folder))
                        if "正极" in current_folder and "OK" in current_folder:
                            leaf_folders.append(current_folder)
                        #leaf_folders.append(current_folder)
                else:
                    # 将子文件夹加入栈中继续搜索
                    stack.extend(subfolders)

            except ClientError as e:
                logger.error(f"列出子文件夹失败: {e.response['Error']['Message']}")
                raise
            except Exception as e:
                logger.error(f"列出子文件夹失败: {str(e)}")
                raise

        #logger.info(f"在 {parent_folder} 下找到 {len(leaf_folders)} 个最后一层子文件夹")
        return leaf_folders
if __name__ == '__main__':
        folder_path="文件所在的文件夹路径"
        CONFIG = {
            'endpoint': 'http://<ip>:<port>',
            'access_key': 'xxxxxxxxxxxxxxx',
            'secret_key': 'xxxxxxxxxxxxxxxx',
            'bucket_name': '桶名'
              # 存储桶中的图片文件夹路径,以/结尾
                  }
        try:
            # 创建查看器实例并连接
            viewer = XSkyStorageViewer(
                endpoint=CONFIG['endpoint'],
                access_key=CONFIG['access_key'],
                secret_key=CONFIG['secret_key'],
                bucket_name=CONFIG['bucket_name']
            )
            viewer.connect()
            # 列出图片
            image_folder = CONFIG['image_folder']
            subfolders = viewer.list_subfolders(image_folder)
            img_num=0
            #一层一层的读取文件夹子路径
            for folder in subfolders:
                subfolders_ = viewer.list_subfolders(folder)
                #文件夹二级路径
                for folder__ in subfolders_:
                    #文件夹子路径
                    leaf_folders = viewer.list_subfolders_(folder__)
                    for leaf_folders_ in leaf_folders:
                        images = viewer.list_images(leaf_folders_)
                        for image in images:
                            #展示图片
                            img=viewer.display_image(image)
                            
                            if img is None:
                                print(f"无法读取图片: {image}")
                                continue              
        except Exception as e:
            logger.critical(f"程序运行失败: {str(e)}")

四、注意事项:

      1、确保登录的账号和APIKEY正常;2、需要确定桶名和文件夹的路径。 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值