这一期遇到的问题,是我在把svs格式的切片分割patch时,提示的与OpenSlideError相关的问题。
首先怀疑指定路径下有openslide不支持的文件格式,于是先查看所有文件的格式类型。
import os
from pathlib import Path
def check_file_types(folder_path):
file_types = {}
# 遍历文件夹中的所有文件
for root, dirs, files in os.walk(folder_path):
for file in files:
file_extension = Path(file).suffix
if file_extension in file_types:
file_types[file_extension] += 1
else:
file_types[file_extension] = 1
return file_types
if __name__ == "__main__":
folder_path = "/data2/data2_mailab015/24-11-25/sysucc/three_patch_2_ruofan" # 替换为你要检查的文件夹路径
result = check_file_types(folder_path)
print(result)
结果显示都是svs格式,理论上不会报错,但是出问题了,所以我们需要继续排除。
知识星球
如需获取推文中提及的各种资料,欢迎加入我的知识星球!
我们已经确认了文件格式没有问题,所以我产生以下两个怀疑:
为了解决上述两个怀疑,我分别做了两件事。
首先,将2400个文件拆分存储到8个的文件夹中,各文件夹分别执行patch分割任务。此外,原来的代码在遇到报错后会直接终止后续的进程,并且不会提示目前已经处理到哪个文件。
这会导致我在排除问题的时候,无法定位到具体的文件,所以我修改了代码,会显示目前处理哪个文件,并且在遇到报错后会跳过当前文件继续执行,并记录所有未能正确处理的切片,最后输出一个列表。
增加这两个功能有以下这些好处:
代码实现
要想实现上面提到的两个功能,我们需要修改主程序,修改前的代码如下。
def main(args):
print(args, args.__dict__)
slide_folder_path = '/path'
print(os.listdir(slide_folder_path))
for slide_name in tqdm(os.listdir(slide_folder_path)):
#print(slide_name)
slide_path = os.path.join(slide_folder_path, slide_name)
args.slide_file = slide_path
tile_factory = TileFactory(args.slide_file, args.tile_size, args.overlap, output_path=args.output_path,
num_workers=args.num_workers)
tile_factory.make_overview()
tile_factory.make_tiles()
修改后如下。
def main(args):
print(args, args.__dict__)
slide_folder_path = '/path'
print(os.listdir(slide_folder_path))
# 用于记录未能正确处理的文件
failed_files = []
for slide_name in tqdm(os.listdir(slide_folder_path)):
slide_path = os.path.join(slide_folder_path, slide_name)
args.slide_file = slide_path
try:
# 尝试处理文件
tile_factory = TileFactory(args.slide_file, args.tile_size, args.overlap, output_path=args.output_path,
num_workers=args.num_workers)
tile_factory.make_overview()
tile_factory.make_tiles()
except OpenSlideError as e:
# 捕获 OpenSlideError 异常并记录错误文件
print(f"Error processing file {slide_path}: {e}")
failed_files.append(slide_path)
except Exception as e:
# 捕获其他可能的异常并记录错误文件
print(f"Unexpected error processing file {slide_path}: {e}")
failed_files.append(slide_path)
# 输出未能正确处理的文件列表
if failed_files:
print("\nThe following files failed to process:")
for file in failed_files:
print(file)
else:
print("\nAll files were processed successfully.")
要将 2401 个文件拆分为 8 个文件夹,且每个文件夹的内容不能重复,可以使用 Python 的
os和shutil模块来实现。
获取文件列表:
os.listdir() 获取文件夹中的所有文件。.svs 文件。计算每个文件夹的文件数量:
2401 // 8 = 300,剩余的 1 个文件可以分配到任意一个文件夹。创建目标文件夹:
os.makedirs() 创建 8 个目标文件夹。移动文件:
shutil.move() 将文件移动到对应的目标文件夹中。import os
import shutil
def split_files_into_folders(source_folder, num_folders=8):
# 获取所有 .svs 文件
files = [f for f in os.listdir(source_folder) if f.endswith(".svs")]
total_files = len(files)
print(f"Total .svs files found: {total_files}")
# 计算每个文件夹的文件数量
files_per_folder = total_files // num_folders
remainder = total_files % num_folders
print(f"Files per folder: {files_per_folder}, Remainder: {remainder}")
# 创建目标文件夹
target_folders = [os.path.join(source_folder, f"folder_{i+1}") for i in range(num_folders)]
for folder in target_folders:
os.makedirs(folder, exist_ok=True)
# 分配并移动文件
start_index = 0
for i, folder in enumerate(target_folders):
# 计算当前文件夹的文件数量
end_index = start_index + files_per_folder + (1 if i < remainder else 0)
# 获取当前文件夹的文件列表
files_to_move = files[start_index:end_index]
# 移动文件
for file in files_to_move:
shutil.move(os.path.join(source_folder, file), os.path.join(folder, file))
print(f"Moved {len(files_to_move)} files to {folder}")
# 更新起始索引
start_index = end_index
if __name__ == "__main__":
# 指定源文件夹路径
source_folder = "/path/to/your/svs/files" # 替换为你的文件夹路径
split_files_into_folders(source_folder)
假设源文件夹 /path/to/your/svs/files 中有 2401 个 .svs 文件,运行代码后,输出如下:
Total .svs files found: 2401
Files per folder: 300, Remainder: 1
Moved 301 files to /path/to/your/svs/files/folder_1
Moved 300 files to /path/to/your/svs/files/folder_2
Moved 300 files to /path/to/your/svs/files/folder_3
Moved 300 files to /path/to/your/svs/files/folder_4
Moved 300 files to /path/to/your/svs/files/folder_5
Moved 300 files to /path/to/your/svs/files/folder_6
Moved 300 files to /path/to/your/svs/files/folder_7
Moved 300 files to /path/to/your/svs/files/folder_8
备份数据:
在运行代码之前,建议先备份源文件夹中的数据,以防意外。
路径问题:
确保 source_folder 是正确的路径。如果路径中包含空格或特殊字符,建议使用原始字符串(如 r"/path/to/your/svs/files")。
权限问题:
确保程序有权限读取源文件夹和写入目标文件夹。
通过这段代码,你可以轻松将 2401 个文件均匀分配到 8 个文件夹中,且每个文件夹的内容不会重复。
如果我们想关掉终端后,代码仍然能够持续运行,则需要使用nohup函数。
nohup python -u main2.py &
如果你想将日志输出到指定的文件(例如 scraw.log),可以使用重定向符号 > 和 2>&1 来指定日志文件。例如:
nohup python -u main2.py > scraw.log 2>&1 &
注意,这个指令是把日志文件存在当前路径。
nohup python -u main2.py > /path/to/logs/my_log.log 2>&1 &
追加日志
上面是默认覆盖日志文件的,如果希望每次运行脚本时将日志追加到现有文件而不是覆盖,可以使用 >> 代替 >。
例如:
nohup python -u main2.py >> my_log.log 2>&1 &
停止后台任务
如果需要停止后台运行的脚本,可以使用 ps 查找进程 ID,然后使用 kill 终止进程。例如:
ps aux | grep main2.py # 查找进程 ID
kill <PID> # 终止进程
pkill -f main2.py #直接终止与脚本相关的所有进程
要删除文件夹内指定时间之前的所有文件,可以使用 Python 的
os和time模块来实现。
以下是一个完整的代码示例,它会遍历文件夹中的所有文件,检查文件的修改时间,并删除早于指定时间的文件。
获取文件列表
使用 os.listdir() 获取文件夹中的所有文件。
检查文件修改时间
os.path.getmtime() 获取文件的最后修改时间。删除文件
如果文件的修改时间早于指定时间,使用 os.remove() 删除文件。
import os
import time
def delete_files_older_than(folder_path, days):
# 获取当前时间
current_time = time.time()
# 计算指定时间之前的时间戳
time_threshold = current_time - (days * 800) # 800 秒 = 1 天
# 遍历文件夹中的所有文件
for filename in os.listdir(folder_path):
file_path = os.path.join(folder_path, filename)
# 检查是否为文件(排除文件夹)
if os.path.isfile(file_path):
# 获取文件的最后修改时间
file_mtime = os.path.getmtime(file_path)
# 如果文件的修改时间早于指定时间,删除文件
if file_mtime < time_threshold:
print(f"Deleting file: {filename} (Last modified: {time.ctime(file_mtime)})")
os.remove(file_path)
if __name__ == "__main__":
# 指定文件夹路径
folder_path = "//data2/data2_mailab015/get_patch/sysucc/three_patch_2_ruofan" # 替换为你的文件夹路径
# 指定天数(删除早于多少天前的文件)
days = 30 # 例如,删除 30 天前的文件
delete_files_older_than(folder_path, days)
计算时间阈值:
time.time() 获取当前时间的时间戳。time_threshold = current_time - (days * 800) 计算指定天数之前的时间戳。遍历文件夹:
os.listdir(folder_path) 获取文件夹中的所有文件。os.path.isfile(file_path) 检查是否为文件(排除文件夹)。检查文件修改时间:
os.path.getmtime(file_path) 获取文件的最后修改时间。time_threshold,则删除文件。删除文件:
os.remove(file_path) 删除文件。假设文件夹 /path/to/your/folder 中有以下文件:
file1.txt (最后修改时间: 2023-09-01)
file2.txt (最后修改时间: 2023-10-01)
file3.txt (最后修改时间: 2023-10-15)
运行代码后,输出如下:
Deleting file: file1.txt (Last modified: Fri Sep 1 12:00:00 2023)
如果需要递归删除子文件夹中的文件,可以使用 os.walk() 遍历文件夹。
import os
import time
def delete_files_older_than(folder_path, days):
current_time = time.time()
time_threshold = current_time - (days * 800)
for root, dirs, files in os.walk(folder_path):
for filename in files:
file_path = os.path.join(root, filename)
file_mtime = os.path.getmtime(file_path)
if file_mtime < time_threshold:
print(f"Deleting file: {file_path} (Last modified: {time.ctime(file_mtime)})")
os.remove(file_path)
if __name__ == "__main__":
folder_path = "/data2/data2_mailab015/get_patch/sysucc/three_patch_2_ruofan"
days = 30
delete_files_older_than(folder_path, days)
通过这段代码,你可以轻松删除文件夹内指定时间之前的所有文件。
结束语
本期推文的内容就到这里啦,如果需要获取医学AI领域的最新发展动态,请关注小罗的推送!如需进一步深入研究,获取相关资料,欢迎加入我的知识星球!
因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- vipyiyao.com 版权所有 湘ICP备2023022495号-8
违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务