views:

234

answers:

2

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:

# -*- 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/κόσμε" [email protected]:/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:

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 [email protected]:/volatile/bac kup/vaidab/2010-03-03.15_41_56/'

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

+1  A: 
  • Don't use shell=True. EVER. It needlessy invokes a shell to call your program.
  • 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):

# -*- 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'), 
           '[email protected]:/volatile/backup/vaidab/2010-03-03.15_41_56/', 
           '--link-dest=../2010-03-03.15_00_57']

execute(command)
nosklo
doesn't work, same problem (check above)
vaidab
Well, then it seems your filesystem is not utf-8. What does `sys.getfilesystemencoding()` returns? Perhaps try using that as encoding?
nosklo
it returns mbcs. I modified to .encode('mbcs') and:>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" /cygdrive/c/??s\xb5e [email protected]:/volatile/backup/vaidab/2010-03-03.15_41_56/'...ERRS: 'rsync: link_stat "/cygdrive/c/??s\xc2\xb5e" failed: No such file or directory
vaidab
@vaidab: are you able to run the command on the command prompt? Which encoding is your terminal/console program using?
nosklo
After installing the Italian language I get:sys.getdefaultencoding() asciisys.stdout.encoding() cp437
vaidab
@vaidab: which editor are you using to edit the source file? Is the editor able to save the file in utf-8?
nosklo
I'm using vim and the utf-8 chars I type in the source file work ok on linux (I create a directory with them and test its existence).
vaidab
A: 

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?

John Machin
true, It was a leftover, sorry for that.
vaidab