How to return from with statement?

喜你入骨 提交于 2019-12-11 11:33:57

问题


I have a function that tries some list of params to connect to ftp and connects to the first server that it could.

def connect(params):
    for user, passw, host in params:
        try:
            import pdb;pdb.set_trace()
            with FTPHost(host, user, passw) as h:
                return h
        except FTPError as e:
            logger.debug("Can't connect to ftp error is {}".format(e))
    else:
        raise Exception(
            "Can't connect to ftp server with none of the {}".format(params)
        )

Further in code I'm trying something like that

host = connect(*args)
host.walk()

But right after return the connection is closed. This is probably how it should work, I guess, although I hoped that it wouldn't. But now I don't really know how to encapsulate trials of connection from application logic properly.

I mean certainly I could change this into continuation passing style (this is correct name for that, right?)

def connect(params, some_application_function):
    for user, passw, host in params:
        try:
            import pdb;pdb.set_trace()
            with FTPHost(host, user, passw) as host:
                some_application_function(host)
        except FTPError as e:
            logger.debug("Can't connect to ftp error is {}".format(e))
    else:
        raise Exception(
            "Can't connect to ftp server with none of the {}".format(params)
        )

But this seems less readable. Are there any other options?


回答1:


I would probably convert your connect function into a context manager itself that internally invokes your FTPHost context manager's magic methods:

class FTPConnector:
    def __init__(self, params):
        self.params = params
    def __enter__(self):
        for user, passw, host in params:
            try:
                # import pdb;pdb.set_trace()  # not sure what you want to do with that...
                self.h_context = FTPHost(host, user, passw)
                return self.h_context.__enter__()
            except FTPError as e:
                logger.debug("Can't connect to ftp error is {}".format(e))
        else:
            raise Exception(
                "Can't connect to ftp server with none of the {}".format(params)
            )
    def __exit__(self, exc_type, exc_value, traceback):
        return self.h_context.__exit(exc_type, exc_value, traceback)

Now you could run this in your main function:

with FTPConnector(params) as host:
    host.walk()
    # do something useful with the connection here

# here the connection gets closed again



回答2:


Maybe move the with statement to outside the connect function?

def connect(params):
    for user, passw, host in params:
        try:
            import pdb;pdb.set_trace()
            return FTPHost(host, user, passw)
        except FTPError as e:
            logger.debug("Can't connect to ftp error is {}".format(e))
    else:
        raise Exception(
            "Can't connect to ftp server with none of the {}".format(params)
        )

def main():
    with connect(params) as h:
        do_something(h)


来源:https://stackoverflow.com/questions/36857600/how-to-return-from-with-statement

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!