提取 "with" 语句中的代码并将其从运行时删除
Extract the code in a "with" statement and remove it from runtime
上下文
我正在尝试创建一个“环境”上下文管理器。将其视为根据上下文管理器的参数选择在本地或远程执行某些代码:
with PythonExecutor(env="local"):
x = 1
assert x == 1
运行 该代码会在进程中。但是,将 env
参数更改为 "remote"
将连接到 SSH 并远程执行代码。
感谢 ,我设法将 with
块中的代码提取为 __exit__
方法中的字符串,并且 SSH 部分很简单(与该问题无关) ).
问题
如何防止 with
块中的代码进入 运行 进程中?上下文管理器始终遵循:
- 呼叫
__enter__
- 执行
with
块中的代码
- 呼叫
__exit__
这意味着即使我选择"remote"
执行,代码会在__enter__
或__exit__
远程执行,但仍然会在本地执行。换句话说,有什么方法可以跳过第 2 步吗?我开始研究 运行 时间字节码操作,但它变得有点毛茸茸了……
也欢迎针对原始问题的其他解决方案(运行以优雅的方式在不同环境中编写代码)
在 functions 上使用装饰器怎么样? (您确实说过欢迎使用其他解决问题的方法...)
def remote(func):
def execute():
print(f"running {func.__name__} remotely")
return func()
return execute
@remote
def func():
print("hello")
func()
或者对于相同的语义:
def Env(env="local"):
if env == "remote":
return remote
else:
return lambda x: x
@Env("remote")
def func2():
print("hello again")
@Env("local")
def func3():
print("hello again")
func2()
func3()
我知道你几乎肯定想到过这种方法并出于某种原因拒绝了它,但偶尔,值得一提。
我不知道是否可以将 with 块的内容放入某种类似函数的东西中。如所写,此方法当然需要您将代码定义为函数。
它有点老套,需要稍微更改 with 块的代码,但您可以使 __enter__
方法 return 成为一个在 env == 'remote'
时引发错误的函数。然后在远程情况下,你会得到一个本地错误,然后处理 __exit__
块中的所有其他内容。
class PythonExecutor:
def __init__(self, env):
self.env = env
def __enter__(self):
def switch():
if self.env == 'remote':
raise Exception # Probably some custom exception for only this purpose
return switch
def __exit__(self, exctype, excinst, exctb):
# do ssh stuff here depending on exctype
...
with PythonExecutor(env='remote') as switch:
switch()
print('hello')
上下文
我正在尝试创建一个“环境”上下文管理器。将其视为根据上下文管理器的参数选择在本地或远程执行某些代码:
with PythonExecutor(env="local"):
x = 1
assert x == 1
运行 该代码会在进程中。但是,将 env
参数更改为 "remote"
将连接到 SSH 并远程执行代码。
感谢 with
块中的代码提取为 __exit__
方法中的字符串,并且 SSH 部分很简单(与该问题无关) ).
问题
如何防止 with
块中的代码进入 运行 进程中?上下文管理器始终遵循:
- 呼叫
__enter__
- 执行
with
块中的代码 - 呼叫
__exit__
这意味着即使我选择"remote"
执行,代码会在__enter__
或__exit__
远程执行,但仍然会在本地执行。换句话说,有什么方法可以跳过第 2 步吗?我开始研究 运行 时间字节码操作,但它变得有点毛茸茸了……
也欢迎针对原始问题的其他解决方案(运行以优雅的方式在不同环境中编写代码)
在 functions 上使用装饰器怎么样? (您确实说过欢迎使用其他解决问题的方法...)
def remote(func):
def execute():
print(f"running {func.__name__} remotely")
return func()
return execute
@remote
def func():
print("hello")
func()
或者对于相同的语义:
def Env(env="local"):
if env == "remote":
return remote
else:
return lambda x: x
@Env("remote")
def func2():
print("hello again")
@Env("local")
def func3():
print("hello again")
func2()
func3()
我知道你几乎肯定想到过这种方法并出于某种原因拒绝了它,但偶尔,值得一提。
我不知道是否可以将 with 块的内容放入某种类似函数的东西中。如所写,此方法当然需要您将代码定义为函数。
它有点老套,需要稍微更改 with 块的代码,但您可以使 __enter__
方法 return 成为一个在 env == 'remote'
时引发错误的函数。然后在远程情况下,你会得到一个本地错误,然后处理 __exit__
块中的所有其他内容。
class PythonExecutor:
def __init__(self, env):
self.env = env
def __enter__(self):
def switch():
if self.env == 'remote':
raise Exception # Probably some custom exception for only this purpose
return switch
def __exit__(self, exctype, excinst, exctb):
# do ssh stuff here depending on exctype
...
with PythonExecutor(env='remote') as switch:
switch()
print('hello')