Search code examples
pythonparamikoioerror

Python (paramiko) - No such file or directory: u'\u012f\u0161-test.xls'


My file name is this file_path=u'įš-test.xls.

When I try this:

from xlrd import open_workbook
wb = open_workbook(file_path)

I get this error:

  File "/usr/local/lib/python2.7/dist-packages/xlrd/__init__.py", line 394, in open_workbook
    f = open(filename, "rb")
IOError: [Errno 2] No such file or directory: u'\u012f\u0161-test.xls'

If I change to:

wb = open_workbook(file_path.encode('utf-8'))

IOError: [Errno 2] No such file or directory: '\xc4\xaf\xc5\xa1-test.xls'

Note There might be a problem with paramiko, because file is taken from remote directory, using this method (if file with unicode name is taken from local directory, it passes fine too):

from contextlib import closing
import socket, os
from paramiko import SSHConfig, SSHClient, AutoAddPolicy, AuthenticationException

    def check_remote_dir(self, cr, uid, ids, direct, arch_dir, gec_type, fmt, context=None):
        rec = self.browse(cr, uid, ids, context=context)[0]
        with closing(SSHClient()) as ssh:
            ssh.set_missing_host_key_policy(AutoAddPolicy())
            try:
                ssh.connect(rec.host, username=rec.user, password=rec.password)
            except socket.gaierror:
               raise orm.except_orm(_('Error!'),
                    _("Name or service '%s' not known") % (rec.host))
            except AuthenticationException:
               raise orm.except_orm(_('Authentication Fail!'),
                    _("Bad username or password"))                    
            with closing(ssh.open_sftp()) as sftp:
                try:
                    sftp.chdir(direct)
                except IOError:
                    raise orm.except_orm(_('Error!'),
                        _('Remote directory %s not found') % (direct)) 
                try:
                    os.chdir(arch_dir)
                except OSError:
                    raise orm.except_orm(_('Error!'),
                        _('Archive directory %s not found') % (arch_dir))                         
                gec_obj = self.pool.get('card.gec.data')
                for f in sftp.listdir():
                    for fmt in fmt.replace(' ', '').split(','): #removing any whitespace and then splitting in list
                        length = len(fmt) + 1
                        if f[-length:] == ".%s" % (fmt):
                            gec_id = gec_obj.create(cr, uid, {'name': f, 'gec_type': gec_type})
                            self._resolve_parse(cr, uid, gec_id, gec_obj, gec_type, f, context=context)
                            self.archive_file(f, None, add_dt=True, remote=True)
                            sftp.remove(f)
                            break #only need to check till first occurence

P.S. method params like cr, uid, ids are application specific and are not really related with remote file handling, so you can ignore those

Update I noticed this in a log:

2015-02-03 10:23:48,143 10430 INFO amb_test paramiko.transport.sftp: [chan 1] Opened sftp connection (server version 3)
is-test.xls
2015-02-03 10:23:48,162 10430 INFO amb_test paramiko.transport.sftp: [chan 1] sftp session closed.

This happens and then I get that error. Could it be that session is closed before file is used?

Update2 It seems something is wrong with sftp.listdir(). When I try to use filename from it, like using standard open, it gives error, that there is no such file as I guess it only checks on local directory (I don't get it how it was working before..). If I try to open with sftp.open(), then it works.

How could I use remote path to open it in local server?


Solution

  • It seems there was something wrong with remote file paths. When I got a remote path and tried to directly open from it, it would not see it and would throw an error that such file not found.

    So I rewritten my methods, to handle remote files a bit differently. Now it just downloads it and opens it locally, instead of remotely (and only after parsing saving it locally).

    If there are better approaches, please feel free to post them as answers. So here my new methods that solved my problem:

    def check_remote_dir(self, cr, uid, ids, rem_dir, local_dir, arch_dir, gec_type, fmt, context=None):
        """
        Only used to check remote directories and download files
        locally
        """
        rec = self.browse(cr, uid, ids, context=context)[0]
        with closing(SSHClient()) as ssh:
            ssh.set_missing_host_key_policy(AutoAddPolicy())
            try:
                ssh.connect(rec.host, username=rec.user, password=rec.password)
            except socket.gaierror:
               raise orm.except_orm(_('Error!'),
                    _("Name or service '%s' not known") % (rec.host))
            except AuthenticationException:
               raise orm.except_orm(_('Authentication Fail!'),
                    _("Bad username or password"))                    
            with closing(ssh.open_sftp()) as sftp:
                try:
                    sftp.chdir(rem_dir)
                except IOError:
                    raise orm.except_orm(_('Error!'),
                        _('Remote directory %s not found') % (rem_dir)) 
                try:
                    os.chdir(local_dir)
                except OSError:
                    raise orm.except_orm(_('Error!'),
                        _('Archive directory %s not found') % (arch_dir))                         
                gec_obj = self.pool.get('card.gec.data')
                for f in sftp.listdir():
                    sftp.get(f, f)
                    sftp.remove(f)
        #handle files locally
        rec.check_dir(local_dir, arch_dir, gec_type, fmt)  
    
    def check_dir(self, cr, uid, ids, direct, arch_dir, gec_type, formats, context=None):
        rec = self.browse(cr, uid, ids, context=context)[0]
        try:
            os.chdir(direct)
        except OSError:
            raise orm.except_orm(_('Error!'),
                _('Directory %s not found') % (direct))                
        directs = os.listdir(direct)
        gec_obj = self.pool.get('card.gec.data')
        formats = formats.replace(' ', '').split(',') # Removing any whitespace and then splitting in list
        for f in directs:
            for fmt in formats: 
                length = len(fmt) + 1
                if f[-length:] == ".%s" % (fmt):
                    gec_id = gec_obj.create(cr, uid, {'name': f, 'gec_type': gec_type})
                    self._resolve_parse(cr, uid, gec_id, gec_obj, gec_type, f, context=context)
                    self.archive_file(f, arch_dir, add_dt=True)
                    break #only need to check till first occurence