ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Python子脚本消耗了所有的stdin

2019-10-28 06:00:49  阅读:207  来源: 互联网

标签:bash stdin linux python


在bash脚本中运行python脚本时,我发现了raw_input / readline的某些奇怪行为.

简而言之,当一次将所有stdin(每个条目用换行分隔)传递给父脚本时,bash子脚本将仅采用其所需的stdin,而python子脚本将消耗所有stdin,不留任何内容为下一个孩子.我想出一个简单的例子来说明我的意思:

父脚本(parent.sh)

#!/bin/bash

./child.sh
./child.sh
./child.py
./child.py

Bash子脚本(child.sh)

#!/bin/bash

read -a INPUT
echo "sh: got input: ${INPUT}"

Python子脚本(child.py)

#!/usr/bin/python -B

import sys

INPUT = raw_input()
print "py: got input: {}".format(INPUT)

预期结果

./parent.sh <<< $'aa\nbb\ncc\ndd'
>> sh: got input: aa
>> sh: got input: bb
>> py: got input: cc
>> py: got input: dd

实际结果

./parent.sh <<< $'aa\nbb\ncc\ndd\n'
>> sh: got input: aa
>> sh: got input: bb
>> py: got input: cc
>> Traceback (most recent call last):
>>   File "./child.py", line 5, in <module>
>>     INPUT = raw_input()
>> EOFError: EOF when reading a line

raw_input似乎清除了stdin中的所有其余行.使用sys.stdin.readline代替raw_input不会引发EOFError,但是接收到的输入是一个空字符串,而不是预期的’dd’.

这是怎么回事如何避免这种行为,以便最后一个子脚本收到预期的输入?

编辑:可以肯定的是,我向stdin添加了几行,结果是相同的:

./parent.sh <<< $'aa\nbb\ncc\ndd\nff\nee\n'
>> sh: got input: aa
>> sh: got input: bb
>> py: got input: cc
>> Traceback (most recent call last):
>>   File "./child.py", line 5, in <module>
>>     INPUT = raw_input()
>> EOFError: EOF when reading a line

解决方法:

这是演示同一问题的更简单方法:

printf "%s\n" foo bar | {
    head -n 1
    head -n 1
}

从所有人的角度来看,这看起来应该打印两行,但该栏却神秘地丢失了.

这是因为阅读线是一个谎言. UNIX编程模型不支持它.

取而代之的是,基本上所有工具所做的工作都是消耗整个缓冲区,划分出第一行,然后将缓冲区的其余部分留给下一次调用.对于head,Python raw_input(),C fgets(),Java BufferedReader.readLine()以及几乎所有其他内容都是如此.

由于UNIX将整个缓冲区视为已消耗,因此无论程序最终实际使用了多少缓冲区,因此在程序退出时,其余缓冲区将被丢弃.

但是bash可以解决该问题:它逐字节读取直到到达换行符为止.这是非常低效的,但是它允许read只消耗流中的一行,其余的留给下一过程.

您可以通过打开未缓冲的原始读取器在Python中执行相同的操作:

import sys
import os
f = os.fdopen(sys.stdin.fileno(), 'rb', 0)
line=f.readline()[:-1]
print "Python read: ", line

我们可以用相同的方式测试:

printf "%s\n" foo bar | {
    python myscript
    python myscript
}

版画

Python read: foo
Python read: bar

标签:bash,stdin,linux,python
来源: https://codeday.me/bug/20191028/1950236.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有