一、理解星辰天合(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、需要确定桶名和文件夹的路径。
1305

被折叠的 条评论
为什么被折叠?



