Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux:导入Python(ncurses)脚本、stdin和termios_Python_Linux_Pipe_Ncurses_Termios - Fatal编程技术网

Linux:导入Python(ncurses)脚本、stdin和termios

Linux:导入Python(ncurses)脚本、stdin和termios,python,linux,pipe,ncurses,termios,Python,Linux,Pipe,Ncurses,Termios,显然,这几乎是一个“复制品”;但是,我认为这个案例稍微复杂一些(并且它不是特定于Windows的,正如该线程的结论那样) 我目前正在尝试用Python编写一个简单的脚本:我想通过命令行参数为脚本提供输入;或者通过“管道”-将一个字符串添加到此脚本-并让脚本使用curses终端界面显示此输入字符串 下面给出了完整的脚本,这里称为testcurses.py。问题是,每当我尝试实际的管道时,它似乎会弄乱stdin,并且诅咒窗口永远不会显示。这是一个终端输出: ## CASE 1: THROUGH CO

显然,这几乎是一个“复制品”;但是,我认为这个案例稍微复杂一些(并且它不是特定于Windows的,正如该线程的结论那样)

我目前正在尝试用Python编写一个简单的脚本:我想通过命令行参数为脚本提供输入;或者通过“管道”-将一个字符串添加到此脚本-并让脚本使用
curses
终端界面显示此输入字符串

下面给出了完整的脚本,这里称为
testcurses.py
。问题是,每当我尝试实际的管道时,它似乎会弄乱stdin,并且
诅咒
窗口永远不会显示。这是一个终端输出:

## CASE 1: THROUGH COMMAND LINE ARGUMENT (arg being stdin):
##
$ ./testcurses.py -
['-'] 1
stdout/stdin (obj): <open file '<stdout>', mode 'w' at 0xb77dc078> <open file '<stdin>', mode 'r' at 0xb77dc020>
stdout/stdin (fn): 1 0
env(TERM): xterm xterm
stdin_termios_attr [27906, 5, 1215, 35387, 15, 15, ['\x03', ... '\x00']]
stdout_termios_attr [27906, 5, 1215, 35387, 15, 15, ['\x03', ... '\x00']]
opening -
obj <open file '<stdin>', mode 'r' at 0xb77dc020>
TYPING blabla HERE
wr TYPING blabla HERE

at end
before curses TYPING blabla HERE
#
# AT THIS POINT:
# in this case, curses window is shown, with the text 'TYPING blabla HERE'
# ################


## CASE 2: THROUGH PIPE
##
## NOTE I get the same output, even if I try syntax as in SO1057638, like:
## python -c "print 'TYPING blabla HERE'" | python testcurses.py -
##
$ echo "TYPING blabla HERE" | ./testcurses.py -
['-'] 1
stdout/stdin (obj): <open file '<stdout>', mode 'w' at 0xb774a078> <open file '<stdin>', mode 'r' at 0xb774a020>
stdout/stdin (fn): 1 0
env(TERM): xterm xterm
stdin_termios_attr <class 'termios.error'>::(22, 'Invalid argument')
stdout_termios_attr [27906, 5, 1215, 35387, 15, 15, ['\x03', '\x1c', '\x7f', '\x15', '\x04', '\x00', '\x01', '\xff', '\x11', '\x13', '\x1a', '\xff', '\x12', '\x0f', '\x17', '\x16', '\xff', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00']]
opening -
obj <open file '<stdin>', mode 'r' at 0xb774a020>
wr TYPING blabla HERE

at end
before curses TYPING blabla HERE
#
# AT THIS POINT:
# script simply exits, nothing is shown 
# ################

如果不让父进程参与进来,就无法实现这一点。幸运的是,有一种方法可以使用:

最后,您可以通过首先运行子shell来解决命令行中难看的语法:

$ exec 3<&0  # spawn subshell
$ echo "foo" | ./pipe.py  # works
$ echo "bar" | ./pipe.py  # still works
$exec 3问题是,每当我尝试实际的管道时,它似乎会弄乱stdin,而且诅咒窗口永远不会显示。
[…剪断…]
就我所见,问题是:-每当我们将字符串导入Python脚本时,Python脚本就会丢失对终端的引用,即stdin,并注意到被替换的stdin不再是termios结构-并且由于stdin不再是终端,curses.initscr()会立即退出,而不会呈现任何内容。
实际上,curses窗口确实会显示出来,但是由于您的新stdin上没有更多的输入,
myscreen.getch()
会立即返回。因此,它与测试stdin是否是终端的诅咒无关

因此,如果您想使用myscreen.getch()和其他curses输入函数,您必须重新打开终端。在Linux和*nix系统上,通常有一个称为
/dev/tty
的设备,它指向当前终端。因此,您可以执行以下操作:

f=open("/dev/tty")
os.dup2(f.fileno(), 0)

在您致电
myscreen.getch()

之前,先生,谢谢您简洁有效的回答:)我确实使用了
bash
,因为我使用的是ubuntulucid。我的例子,更新了您的更改,可以找到如下;它应该用“
”(echo“blabla”|/testcurses-stdin.py-)3PS调用:我必须承认我已经看过数百次了——也是在我发布这个之前——结果总是让我困惑;我真的很难想出正确的解决办法。另外,由于我非常喜欢单行程序,因此“
命令行上丑陋的语法”
”实际上是最受欢迎的-我不喜欢的事情之一是运行“
exec 3Thanks,ninjalj”,这很好地解释了这一点-它帮助我更好地理解管道和标准I/O是如何工作的!顺便说一句,我对使用“
myscreen.getch()
”并不感兴趣-我想做的是,将原始的“未格式化”数据导入这个脚本,让脚本解析数据,并在屏幕上使用
ncurses
格式化,就像“实时”一样(这是一整套不同的问题-但是理解复制
stdin
的必要性是一个真正的障碍)。干杯!有趣的是,如果你想让脚本无限期运行,而不使用
myscreen.getch()
,你发布的脚本已经运行了,只是退出的速度太快了,以至于没有注意到它。PS:我只是想说我更新了,所以它复制了
/dev/tty
,而不是
fd3
——现在可以用“
echo”blablablabla”直接调用脚本|./testcurses-stdin.py-
”。再次感谢ninjalj-干杯!PSS:也感谢
getch
的评论-我希望我可以调试自己到类似的理解中-但我无法在使用管道运行时执行
gdb
pdb
strace
)因此,对
getch
的洞察是最有价值的(因为我基本上都没有注意到它在那里:)-但我想还是需要它来检测按键退出的情况吧!干杯
strace
对我来说可以很好地处理管道:
echo“地狱世界”| strace-f python testpipe.py-
#!/usr/bin/env python

import sys, os
import curses

output = sys.stdin.readline(100)

# We're finished with stdin. Duplicate inherited fd 3,
# which contains a duplicate of the parent process' stdin,
# into our stdin, at the OS level (assigning os.fdopen(3)
# to sys.stdin or sys.__stdin__ does not work).
os.dup2(3, 0)

# Now curses can initialize.
screen = curses.initscr()
screen.border(0)
screen.addstr(12, 25, output)
screen.refresh()
screen.getch()
curses.endwin()
$ exec 3<&0  # spawn subshell
$ echo "foo" | ./pipe.py  # works
$ echo "bar" | ./pipe.py  # still works
f=open("/dev/tty")
os.dup2(f.fileno(), 0)