在我的 python 文件中,我制作了一个 GUI 小部件,它接受用户的一些输入。我在我的 python 文件中导入了一个 python 模块,它使用 raw_input() 获取一些输入。我必须按原样使用这个模块,我无权更改它。当我运行我的 python 文件时,它会询问我输入(由于导入模块的 raw_input() )。我想在那个地方使用 GUI 小部件输入。如何将用户输入(我们从小部件中获取)作为导入模块的 raw_input() 传递?
1 回答
首先,如果import
将它直接放入您的脚本实际上不是必需的(而且很难想象为什么会这样),您可以将模块(或包裹在它周围的简单脚本)作为一个单独的进程运行,使用subprocess
or pexpect
。
让我们把它具体化。假设你想使用这个愚蠢的模块foo.py
:
def bar():
x = raw_input("Gimme a string")
y = raw_input("Gimme another")
return 'Got two strings: {}, {}'.format(x, y)
先写一个琐碎的foo.wrapper.py
:
import foo
print(foo.bar())
foo.do_thing()
现在,不是直接在您的真实脚本中调用,而是foo_wrapper
作为子进程运行。
我将假设您已经有了要以字符串形式发送的输入,因为这使得答案中不相关的部分变得更简单(事实上,它使它们成为可能——如果您想为此使用一些 GUI 代码,除非您先告诉我们您正在使用哪个 GUI 库,否则我真的无法向您展示如何操作)。
所以:
foo_input = 'String 1\nString 2\n'
with subprocess.Popen([sys.executable, 'foo_wrapper.py'],
stdin=subprocess.PIPE, stdout=subprocess.PIPE) as p:
foo_output, _ = p.communicate(foo_input)
当然,在现实生活中,您将希望使用适当的路径foo_wrapper.py
而不是假设它位于当前工作目录中,但这应该足以说明这个想法。
同时,如果“我无权更改它”只是意味着“我没有(也不应该)对 foo 项目的 github 站点或我们公司 P4 服务器上的相关子树的签入权限”或其他什么,真的简单的答案:叉子,然后换叉子。
即使它拥有像 LGPL 这样的弱 Copyleft 许可证:分叉它,更改分叉,在与原始许可相同的许可下发布您的分叉,然后使用您的分叉。
如果你依赖于每个目标系统上安装的 foo 包,并且不能依赖于你的替换 foo 被安装,那就有点问题了。但是,如果实际调用的函数或方法raw_input
只是 中实际代码的一小部分foo
,您可以通过foo
在运行时进行猴子补丁来修复它。
这导致了最后的可能性:您总是可以raw_input
自行修补。
再一次,我将假设您已经拥有了让事情变得更简单所需的输入。
所以,首先你写一个替换函数:
foo_input = ['String 1\n', 'String 2\n']
def fake_raw_input(prompt):
global foo_input
return foo_input.pop()
现在,有两种方法可以修补它。通常,你想这样做:
import foo
foo.raw_input = fake_raw_input
foo
这意味着该调用中的任何代码raw_input
都将看到您塞入其模块全局变量中的函数,而不是普通的内置函数。除非它做了一些非常时髦的事情(比如直接查找内置函数并将其复制到局部变量或其他东西),否则这就是答案。
如果您需要处理其中一种非常时髦的边缘情况,并且您不介意做一些有问题的事情,您可以这样做:
import __builtin__
__builtin__.raw_input = fake_raw_input
您必须import foo
在问题的第一个位置之前执行此操作。此外,尚不清楚这是故意保证工作,意外保证工作(并且应该在将来修复),还是不保证工作。但它确实有效(至少对于您可能正在使用的 CPython 2.5-2.7 而言)。