Ross Wan's World!

Python, Ajax, PHP and Linux.

Posts Tagged ‘Python 3’

PIL: 批量生成缩略图

Posted by Ross Wan 于 2011/08/29

很久之前, 在 Python 2.5 下写了一个基于 PIL 的批量生成缩略图的脚本, 现将其修改移植到 Python 3下, 其中作了不少修改和完善:

#!bin/pyhton3
# coding=utf8

import os, sys, getopt, functools
from PIL import Image

# 源图片路径
SRC = os.getcwd()
# 目标保存图片的路径
DEST = os.getcwd()
# 缩略图保存的文件夹名称, 最终缩略图的保存路径为 sys.path.join(DEST, THUMB_DIR).
THUMB_DIR = '缩略图'
# 缩放比例
RATE = 0.15
# 缩略图的命名, 在原文件名前加上 THUMB_PREFFIX, 如"thumb_"
THUMB_PREFFIX = ''
# 是否递归搜索子文件夹
IS_RECURSIVE = True

def coroutine(func):
    """ 用于协程的装饰器 """
    @functools.wraps('func')
    def start(*args, **kwargs):
        g = func(*args, **kwargs)
        next(g)
        return g
    return start

@coroutine
def thumb(save_path, rate, thumb_preffix=''):
    img_exts = ('.jpg', '.jepg', '.gif', '.png', '.bmp')
    saved_filenames = set()
    repeatd_times = 0
    while 1:
        img_path = (yield)
        img_ext = os.path.splitext(img_path)[1].lower()
        if not img_ext in img_exts:
            continue
        print(img_path)
        save_filename = '%s%s%s' % (thumb_preffix, os.path.splitext(os.path.split(img_path)[1])[0], img_ext)
        if save_filename in saved_filenames:
            repeatd_times += 1
            save_filename = '%s_%s%s' % (os.path.splitext(save_filename)[0], repeatd_times, img_ext)
        img = Image.open(img_path)
        img.thumbnail((int(img.size[0]*rate), int(img.size[1]*rate)), 1)
        img.save(os.path.join(save_path, save_filename))
        saved_filenames.add(save_filename)
        print('%s %s' % ('Thumb', save_filename))

def process(src, func, is_recursive=True):
    files = []
    dirs = []
    for f in os.listdir(src):
        path = os.path.join(src, f)
        if os.path.isfile(path):
            files.append(path)
        elif is_recursive and os.path.isdir(path) and f.lower() not in ('缩略图', 'thumb', 'thumbs', 'thumbnail', 'thumbnails'):
            dirs.append(path)
    for path in files:
        func.send(path)
    for path in dirs:
        process(path, func, is_recursive)

if __name__ == '__main__':
    src, dest, thumb_dir, rate, thumb_preffix, is_recursive = SRC, DEST, THUMB_DIR, RATE, THUMB_PREFFIX, IS_RECURSIVE
    opts, args = getopt.getopt(sys.argv[1:], 'r:d:p:s')
    print(opts, args)
    for k,v in opts:
        if k == '-r':
            rate = float(v)
        elif k == '-d':
            thumb_dir = v
        elif k == '-p':
            thumb_preffix = v
        elif k == '-s':
            is_recursive = False
    if args:
        args.append(os.getcwd())
        src, dest = args[:2]

    print(src, dest, thumb_dir, rate, thumb_preffix, is_recursive)
    sys.exit()
    save_path = os.path.join(dest, thumb_dir)
    if not os.path.exists(save_path):
        os.makedirs(save_path)

    my_thumb = thumb(save_path, rate, thumb_preffix)
    process(src, my_thumb, is_recursive)
    print('\nDone!')
    input()

脚本依然是基于 PIL 的, 但目前 PIL 的官方还未发布兼容 Python 3 的 Windows 编译版, 幸运的是, 网上可以下载到非官方的编译版本:

http://www.lfd.uci.edu/~gohlke/pythonlibs/#pil

脚本默认递归搜索当前文件夹及子文件夹的图像文件, 然后将生成的缩略图文件放在当前文件夹的”缩略图”文件夹下.当然, 也可修改脚本的参数, 或者在命令行下指定参数:

python3 thumbnial_batch.py -r 0.5 -d ‘thumbs’ -p ‘thumb’ -s 源文件夹 目标文件夹

参数 -r: 指定压缩图片大小的比率;参数 -d: 指定保存缩略图的文件夹名称; 参数 -p: 指定生成的缩略图的文件名添加的前缀; 参数 -s: 只搜索源文件夹,不进行递归搜索子文件夹.
Have fun :>

Posted in Python | Tagged: , , , , | Leave a Comment »

Syncfiles for Python 3: 文件夹同步

Posted by Ross Wan 于 2011/08/28

很久之前在 Python 2.5 下写了个同步两个文件夹的小脚本,  挺有用的, 方便了不少繁琐的资料同步操作, 成了每天必运行的小程序. 今天, 将其更新成兼容 Python 3. 其中有不少修改——之前主要是利用 os.listdir 遍历文件夹,利用 filecmp.dircmp 比较文件夹; 现在,依然用 filecmp.dircmp 来进行比较,但移除了 os.listdir, 因为后来发觉 filecmp.dircmp 来身就提供了 subdirs 方法遍历子文件夹, 而且更为便利, 修改后的脚本的行数也了少不少 :P

#!/bin/python
#coding=utf-8

import filecmp, shutil, os, sys

SRC = r'C:/a'
DEST = r'C:/b'

IGNORE = ['Thumbs.db']

def get_cmp_paths(dir_cmp, filenames):
    return ((os.path.join(dir_cmp.left, f), os.path.join(dir_cmp.right, f)) for f in filenames)

def sync(dir_cmp):
    print(dir_cmp.left)
    for f_left, f_right in get_cmp_paths(dir_cmp, dir_cmp.right_only):
        if os.path.isfile(f_right):
            os.remove(f_right)
        else:
            shutil.rmtree(f_right)
        print('删除 %s' % f_right)
    for f_left, f_right in get_cmp_paths(dir_cmp, dir_cmp.left_only+dir_cmp.diff_files):
        if os.path.isfile(f_left):
            shutil.copy2(f_left, f_right)
        else:
            shutil.copytree(f_left, f_right)
        print('复制 %s' % f_left)
    for sub_cmp_dir in dir_cmp.subdirs.values():
        sync(sub_cmp_dir)

def sync_files(src, dest, ignore=IGNORE):
    if os.path.isfile(src) or os.path.isfile(dest):
        print('只能对文件夹进行同步, 请正确输入源文件夹和目标文件夹...')
        return
    dir_cmp = filecmp.dircmp(src, dest, ignore=IGNORE)
    sync(dir_cmp)
    print('同步完成!')

if __name__ == '__main__':
    src, dest = SRC, DEST
    if len(sys.argv) == 3:
        src, dest = sys.argv[1:3]
    sync_files(src, dest)
    input()


脚本设置了默认的 src 和 dest 参数(源文件夹和目标文件夹), 也可以在运行脚本时指定:

python3 syncfiles_py3k.py your_src your_dest

Have fun~~

Posted in Python | Tagged: , , , , , | Leave a Comment »