I have a backup applications in python that needs to work on Windows. It needs UTF compatibility (to be able to backup directories that contain UTF characters like italian accents). The problem is it uses external programs (plink, cygwin, ssh and rsync) and I can't get them working. The prototype is 32 lines long, please take a look:
我有一个需要在Windows上运行的python备份应用程序。它需要UTF兼容性(能够备份包含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)
Still doesn't work with nosklo's version, check the result:
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/'
python prototype_unicode_new。py rsync。exe -stats -az -numeric-ids -delete - block- io -modify-window=2——no-group -chmod=u=rwX,g=,o= -e "cygnative plink -ssh -2 -batch -pw test"
OUT: '\nNumber of files: 0\nNumber of files transferred: 0\nTotal file size: 0 b ytes\nTotal transferred file size: 0 bytes\nLiteral data: 0 bytes\nMatched data: 0 bytes\nFile list size: 9\nFile list generation time: 0.001 seconds\nFile list transfer time: 0.000 seconds\nTotal bytes sent: 22\nTotal bytes received: 12\n\ nsent 22 bytes received 12 bytes 68.00 bytes/sec\ntotal size is 0 speedup is 0.00\n' ERRS: '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" failed: No such file or directory (2)\nrs ync error: some files/attrs were not transferred (see previous errors) (code 23) at /home/lapo/packaging/rsync-3.0.6-1/src/rsync-3.0.6/main.c(1039) [sender=3.0. 6]\n' RET: 23
:“\ nNumber文件:0 \ nNumber传输的文件:0 \ nTotal文件大小:0 b欧美\ nTotal转移文件大小:0字节\ nLiteral数据:0字节\ nMatched数据:0字节\ nFile列表大小:9 \ nFile列表生成时间:0.001秒\ nFile列表传输时间:0.000秒\ nTotal字节发送:22 \ nTotal字节收到:12 \ n \ nsent 22字节收到12字节68.00字节/秒\ nTotal大小是0加速是0.00 \ n”犯错误:“rsync:6]\ n的RET:23
2 个解决方案
#1
1
- Don't use
shell=True
. EVER. It needlessy invokes a shell to call your program. - 不要使用shell = True。永远。它无需调用shell来调用您的程序。
- Pass the parameters as a list instead of a string.
- 将参数作为列表而不是字符串传递。
This example should work, provided the parameters are right and the rsync.exe is in current folder (or PATH
):
这个示例应该可以工作,只要参数正确,并且rsync。exe在当前文件夹(或路径):
# -*- 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)
#2
0
A piece of code that passeth all understanding:
一段经过所有理解的代码:
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)
What's the point of doctests if you don't run them?
如果不运行doctests,那么doctests的意义是什么?
#1
1
- Don't use
shell=True
. EVER. It needlessy invokes a shell to call your program. - 不要使用shell = True。永远。它无需调用shell来调用您的程序。
- Pass the parameters as a list instead of a string.
- 将参数作为列表而不是字符串传递。
This example should work, provided the parameters are right and the rsync.exe is in current folder (or PATH
):
这个示例应该可以工作,只要参数正确,并且rsync。exe在当前文件夹(或路径):
# -*- 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)
#2
0
A piece of code that passeth all understanding:
一段经过所有理解的代码:
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)
What's the point of doctests if you don't run them?
如果不运行doctests,那么doctests的意义是什么?