Python Unicode 实现 (使用外部程序:cygnative plink ssh rsync)

0 投票
2 回答
1320 浏览
提问于 2025-04-15 20:12

我有一个用Python写的备份应用程序,需要在Windows上运行。它需要支持UTF编码(这样才能备份包含意大利语重音符号的目录)。问题是它使用了一些外部程序(比如plink、cygwin、ssh和rsync),我无法让它们正常工作。这个原型代码有32行,请看一下:

# -*- coding: utf-8 -*-
import subprocess

def safestr(obj, encoding='utf-8'):
    r"""Converts any given object to utf-8 encoded string.

        >>> safestr('hello')
        'hello'
        >>> safestr(u'\u1234')
        '\xe1\x88\xb4'
        >>> safestr(2)
        '2'
    """
    if isinstance(obj, unicode):
        return obj.encode("utf-8")
    elif isinstance(obj, str):
        return obj.encode
    else:
        return str(obj)

def execute(command):
    pipe = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE)
    out, errs = pipe.communicate()
    retcode = pipe.poll()

    print "OUT: " + repr(out)
    print "ERRS: " + repr(errs)
    print "RET: " + str(retcode)


command = u'rsync --stats -az --numeric-ids --delete --blocking-io --modify-window=2 --no-group --chmod=u=rwX,g=,o=  -e \'cygnative plink -ssh -2 -batch  -pw test \' "/cygdrive/c/κόσμε" vaidab@192.168.1.86:/volatile/backup/vaidab/2010-03-03.15_41_56/ --link-dest=../2010-03-03.15_00_57'.encode('utf-8')
execute(command)

用nosklo的版本还是不行,看看结果:

python prototype_unicode_new.py 'rsync.exe --stats -az --numeric-ids --delete --blocking-io --modify-window=2 -- no-group --chmod=u=rwX,g=,o= -e "cygnative plink -ssh -2 -batch -pw test" /cygdr ive/c/\xce\xba\xcf\x8c\xcf\x83\xce\xbc\xce\xb5 vaidab@192.168.1.86:/volatile/bac kup/vaidab/2010-03-03.15_41_56/'

输出结果:'\n文件数量: 0\n传输的文件数量: 0\n总文件大小: 0 字节\n总传输文件大小: 0 字节\n实际数据: 0 字节\n匹配的数据: 0 字节\n文件列表大小: 9\n文件列表生成时间: 0.001 秒\n文件列表传输时间: 0.000 秒\n发送的总字节数: 22\n接收的总字节数: 12\n发送 22 字节 接收 12 字节 68.00 字节/秒\n总大小为 0 加速比为 0.00\n' 错误信息: 'rsync: link_stat "/cygdrive/c/\xc3\x8e\xc2\xba\xc3\x8f\xc5\x92\xc3\x8f\xc 6\x92\xc3\x8e\xc2\xbc\xc3\x8e\xc2\xb5" 失败: 没有这样的文件或目录 (2)\nrs ync 错误: 一些文件/属性没有被传输 (查看之前的错误) (代码 23) 在 /home/lapo/packaging/rsync-3.0.6-1/src/rsync-3.0.6/main.c(1039) [发送方=3.0. 6]\n' 返回码: 23

2 个回答

0

这段代码让人看了很费解:

if isinstance(obj, unicode):
    return obj.encode("utf-8")
elif isinstance(obj, str):
    return obj.encode
    # the above is returning a METHOD ***************************
else:
    return str(obj)

如果你不去运行它们,doctests还有什么意义呢?

1
  • 不要使用 shell=True绝对不要。这样做会多此一举地调用一个命令行窗口来运行你的程序。
  • 把参数作为一个列表传递,而不是用字符串。

只要参数正确,并且 rsync.exe 在当前文件夹里(或者在 PATH 中),这个例子应该可以正常工作:

# -*- coding: utf-8 -*-
import subprocess

def execute(command):
    pipe = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    out, errs = pipe.communicate()
    retcode = pipe.poll()

    print "OUT: " + repr(out)
    print "ERRS: " + repr(errs)
    print "RET: " + str(retcode)
    return out


command = ['rsync.exe', '--stats', '-az', '--numeric-ids', '--delete', 
           '--blocking-io', '--modify-window=2', '--no-group', 
           '--chmod=u=rwX,g=,o=', '-e', 
           'cygnative plink -ssh -2 -batch -pw test', 
           u'/cygdrive/c/κόσμε'.encode('utf-8'), 
           'vaidab@192.168.1.86:/volatile/backup/vaidab/2010-03-03.15_41_56/', 
           '--link-dest=../2010-03-03.15_00_57']

execute(command)

撰写回答