I'm not sure what your end goal is with this code snippet. If you're trying to isolate the effects of modifying env by having it in a class, that's not going to work. It's a module level global in fabric and no matter where you modify it (by assignment like you're doing here) it's going to apply for any subsequent code. What I think you probably really want is this:
from fabric.api import run, execute, task, settings
@task
def custom_runner(command):
"""Runs command with custom key_filename"""
with settings(warn_only=True, key_filename=r"C:\.ssh\dev.pub"):
result = run(command, timeout=5)
return result
result = execute(custom_runner, "uname -a", host="23.23.23.23")
Keep in mind that this can't be used by the "fab" command line utility as-is because it's executing that code (the result = execute...) as soon as fab loads the fabfile. This would be strictly library use.
You can use roledefs to do groups of hosts like this. The result object will be a dictionary where each host is a key and the corresponding values are the return object of the task. You almost never want to use a bare Exception clause, Fabric has its own ways to prevent an exception from causing your program to terminate.