当使用code.InteractiveConsole作为基类时,使用raw_input的覆盖并且只写入write方法。
>>> input()
''
>>> input("data? ")
Traceback (most recent call last):
File "<input>", line 1, in <module>
TypeError: bad argument type for built-in operation
空输入来自通常的控制台窗口(sys.stdin而不是覆盖)。
这些是覆盖:
def raw_input(self, p = ""):
''' input function:
- runs a new thread to simulate input
sys.stdin is not invoked anymore '''
sys.stdout = StdOut # break capture, the idle is frozen.
self.interrupt()
#print("caught shell input", p)
self.fire("stdin", self, p)
self.inline = p
pos = -1
while pos < 0:
time.sleep(0.1)
pos = self.indata.find("\n")
if pos < 0:
l = len(self.indata)
if l:
pos = l
self.inline = ">>> "
self.fire("inputcleared", self, self.inline)
data = self.indata[:pos]
self.indata = self.indata[pos+1:]
self.updateListing(p+""+data+"\n")
sys.stdout = self.out # start capture again, the idle continues.
return data
def write(self, data):
''' stderr simulation:
fires stderr event '''
self.updateListing(data)
self.fire("stderr", self, data)
将方法添加到控制台实例的本地时,它仅适用于控制台命名空间。到目前为止,我在Windows上的Python 3.5上进行了测试。 编辑:很奇怪我在使用参数时在控制台上获得了Ubuntu-Python3.4 +上提到的TypeError,并且与没有参数的Windows上相同。在Ubuntu-Python3.5 +上,TypeError不会引发。 再次编辑:似乎我的写入覆盖在Ubuntu-Python3.4上不起作用。那里发生了什么:S
此列表可以让了解我们找到的解决方案:
>>> class BasicTrigger(object):
instantValue = "Local value"
def read(self, length = 0):
return self.instantValue+"\n"
def readline(self):
return self.instantValue
>>> a = BasicTrigger()
>>> a.read()
'Local value\n'
>>> sys.stdin = a
>>> input()
'Local value'
>>> input('Data: ')
Data: 'Local value'
列表是在InteractiveInterpreter
个实例中创建的,不仅仅是考虑用这样的乐趣替换sys.stdin
。
那里没有使用io.StringIO基类。并且'数据:'被打印(跟踪)但没有换行,因为它无法触发BasicTrigger的数据 - 此时它只是一个重定向。
无论如何,该类型错误的触发真的很奇怪。感谢您的支持。
答案 0 :(得分:0)
raw_input
类的code.InteractiveConsole
方法仅用于控制台自己的输入(例如,要运行的下一行代码)。它不会被调用您在控制台中运行的代码所请求的输入。
如果您希望自定义代码也提供,那么您需要做更多工作。仅在input
中提供替换raw_input
或locals
函数仅适用于简单情况,其中所有输入请求代码都在交互式会话中提供。如果输入是在导入的模块中完成的(它仍然具有普通的内置而不是替换),它将无法工作。
相反,当您在会话中运行代码时,我建议将sys.stdin
替换为其他类似文件的对象。这是一个快速而又脏的实现,它覆盖了runcode
方法,其中一个版本在控制台中运行代码时交换sys.stdin
,但不是其余的时间:
class CustomInputConsole(code.InteractiveConsole):
def __init__(self, input_file):
code.InteractiveConsole.__init__(self) # old style class, so can't use super() here
self.input_file = input_file
def raw_input(self, prompt=""):
self.write(prompt)
line = self.input_file.readline()
if line:
return line.rstrip("\n")
raise EOFError()
def runcode(self, _code):
try:
old_stdin = sys.stdin
sys.stdin = self.input_file
code.InteractiveConsole.runcode(self, _code)
finally:
sys.stdin = old_stdin
这是一个快速演示,使用io.BytesIO
的实例作为输入文件:
>>> con = CustomInputConsole(io.BytesIO("""input()
1+2
"""))
>>> con.interact()
Python 2.7.10 (default, May 23 2015, 09:44:00) [MSC v.1500 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
(CustomInputConsole)
>>> 3
>>>
请注意,从文件类对象中获取的输入不会被回显,如果需要,您需要将其添加到文件对象的逻辑中。