1

As you can see from my code below, I'm using multiple "with" statements to download via SFTP.

I want to raise custom exceptions (or generally get a better idea what went wrong) based on where the error came from.

Usually I'd just wrap stuff in individual exceptions but I'm unsure how to do that here.

The code below doesn't work because my custom exceptions just bubble up, meaning I always get the ConnectionException.

    try:
        with pysftp.Connection(self.sftp_details["host"], username=self.sftp_details["user"],
            private_key=env.root_dir+"/private.ppk", port=self.sftp_details["port"]) as sftp:

            try:
                with sftp.cd(self.sftp_details["folder"]):
                    try:
                        sftp.get(self.sftp_details["filename"],local_filename)
                    except Exception as e:
                        self.logErrorToSheet("The file could not be found on the server.")
                        raise FileNotFoundException(self.sftp_details)

            except Exception as e:
                self.logErrorToSheet("The folder could not be found.")
                ServerFolderNotFoundException(self.sftp_details)

    except Exception as e:
        self.logErrorToSheet("A connection could not be made. (%s)" %(e))
        raise ConnectionException(e, self.sftp_details)

Edit:

Okay so it sounds like I need to do something like:

    try:
    with pysftp.Connection(self.sftp_details["host"], username=self.sftp_details["user"],
        private_key=env.root_dir+"/private.ppk", port=self.sftp_details["port"]) as sftp:
            with sftp.cd(self.sftp_details["folder"]):
                    sftp.get(self.sftp_details["filename"],local_filename)

except Connection as e:
    self.logErrorToSheet("A connection could not be made. (%s)" %(e))
    raise e

except IOError as e:
    self.logErrorToSheet("The file or folder could not be found on the server.")
raise e

I'm not quite sure how I'd tell the difference between a folder error (cd) and a file error but that's another question I can look into.

  • 2
    If you made sure to only catch the exception types relevant for the specific operations going on in each block, that wouldn't be an issue; that is, rather than `except Exception`, catch whatever exception types can actually occur, and ignore the ones you want to fall through. – fuglede Oct 11 '19 at 18:39
  • @fuglede suggestion is most likely the way to go, unless you're specifically trying to set up exception chaining. In which case, take a look at https://stackoverflow.com/questions/16414744/python-exception-chaining – Kal Zekdor Oct 11 '19 at 18:54
  • Looking at the [docs](https://pysftp.readthedocs.io/en/release_0.2.9/pysftp.html?highlight=exception), `pysftp` already throws a wide variety of exception types from its different operations. Why do you feel the need to wrap those in your own types? – 0x5453 Oct 11 '19 at 19:15
  • Thanks all. I've updated my post. Indentations a bit messy but I assume that's what I'm supposed to do? – Charles Bannister Oct 11 '19 at 23:35
  • @CharlesBannister I think you almost got it. The thing is, your custom exceptions were redundant: the only way you could've known at that point what happened was if an exception with the exact same meaning was already raised by the library itself. The only meaningful one is "ConnectionError", as it summarizes what the module was trying to do. The more detailed ones are visible from the stack trace anyway. What you can still do is have a catch-all at the very end, if you want to log unknown exceptions to a file. But remember to reraise it no matter what, otherwise it is dangerous! – Larry Oct 11 '19 at 23:53

0 Answers0