问题
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