如何在Python中通过sys.stdin读取两个不同的文件

问题描述 投票:0回答:2

我想从 sys.stdin 读取两个不同的文件,我可以读取和写入文件,但第一个和第二个文件没有分离。

当我在 Windows 10 和 Python 3.6 中的 cmd 上运行以下代码时:

D:\digit>cat s.csv s2.csv

结果是:

1
2
3
4
5
1
2
3
4
5
6
7

我可以打印这两个文件。

我的Python代码是:

import sys 
import numpy as np

train=[]
test=[]

#Assume below code is function 1 which just and must read s.csv
reader = sys.stdin.readlines()
for row in reader:          
    train.append(int(row[0]))
train = np.array(train)

print(train)

#I need some thing here to make separation
#sys.stdin.close()
#sys.stdin = sys.__stdin__ 
#sys.stdout.flush() 

#Assume below code is function 2 which just and must read s2.csv
reader = sys.stdin.readlines()
for row in reader:          
    test.append(int(row[0]))
test = np.array(test)

print(test)

我在 cmd 提示符下运行以下命令:

D:\digit>cat s.csv s2.csv | python pytest.py

结果是:

[1 2 3 4 5 1 2 3 4 5 6 7]
[]

我需要为下一个文件重置 sys.stdin 吗?我使用了下面的,但没有一个是答案:

sys.stdin.close()
sys.stdin = sys.__stdin__ 
sys.stdout.flush() 
python python-3.x streaming inputstream
2个回答
2
投票

让我尝试解释一下。

d:\digit>cat s.csv s2.csv

只有 1 个输出,而不是 2 个。它的作用是将

file1
的内容“流”到
stdout
,然后将
file2
的内容“流”到
stdout
没有任何暂停或分隔符!

因此只有 1 个输出“流”,然后您可以使用 | 进行重定向。到你的 pyton 脚本:

| pytest.py

因此

pytest.py
将接收 1 个输入“流”,它不知道更好或更多。

如果您想通过

pytest.py
单独处理文件,您可以执行以下操作

D:\digit>cat s.csv | python pytest.py # process the first file
D:\digit>cat s2.csv | python pytest.py # process the second file

或单线:

D:\digit>cat s.csv | python pytest.py && cat s2.csv | python pytest.py

请记住,

pytest.py
实际上正在运行两次。所以你需要为此调整你的 python 脚本。

但是当你编辑 python 脚本时...

你应该做什么: 如果您希望这两个文件都在您的

pytest.py
中,那么您应该编写一些代码来读取 python 脚本中的这两个文件。如果是 csv 结构化数据,那么看看 csv 模块用于读写 csv 文件

[根据评论编辑:]

我可以通过 pandas "pd.read_csv" 读取多个文件,但是我的 问题是我该如何通过 sys.stdin 来做到这一点?

您真的应该质疑为什么您如此专注于使用

stdin
。从 python 脚本中读取它可能会更有效。

如果您必须使用

stdin
,那么您可以部署各种但在Python外部的页眉、页脚、分隔符。一旦定义了这个并且能够执行此操作,您就可以更改 python 中的代码来执行各种功能,具体取决于从
stdin
接收到的页眉/页脚/分隔符。

这一切听起来有点复杂并且容易出错。我强烈建议您重新考虑使用 stdin 作为脚本的输入。或者,请使用您面临的技术要求和限制来更新您的问题,这些要求和限制限制您使用标准输入。

[根据评论编辑:]

我想在 Hadoop 生态系统中加载这些文件并且我正在使用 Hadoop 流媒体为此

不知何故,您需要向您的 python 脚本发出“信号”,表明它正在处理带有新信息的新文件。

假设您有 2 个文件,第一行需要是某种指示文件的“标头”,以及需要对其余数据执行哪个函数,直到收到新的“标头”。

所以可以说,您的“训练”数据以行

@is_train@
为前缀,而您的“测试”数据以行
@is_test@

为前缀

如何在您的环境中做到这一点,不属于此问题的范围

现在重定向到标准输入将在数据之前发送这两个标头。你可以使用 python 来检查这些,例如:

import sys 
import numpy as np

train=[]
test=[]

is_train = False
is_test = False

while True:
    line = sys.stdin.readline()
    if '@stop@' in line:
        break
    if '@is_train@' in line:
        is_train = True
        is_test = False
        continue
    if '@is_test@' in line:
        is_train = False
        is_test = True
        continue
    #if this is csv data, you might want to split on ,
    line = line.split(',')
    if is_train:
        train.append(int(line[0]))
    if is_test:
        test.append(int(line[0]))

test = np.array(test)
train = np.array(train)

print(train)
print(test)

正如您在代码中看到的,您还需要一个“页脚”来确定数据何时结束,在本例中选择了

@stop@

发送页眉/页脚的一种方法可能是:

D:\digit>cat is_train.txt s.csv is_test.txt s2.csv stop.txt | python pytest.py

以及三个额外文件,仅包含适当的页眉或页脚


2
投票

另一个解决方案是:

import sys

train=[]

args = sys.stdin.readlines()[0].replace("\"", "").split()

for arg in args:
    arg=arg.strip()
    with open(arg, "r") as f:
        train=[]
        for line in f:
            train.append(int(line))   
        print(train)    

s.txt 是:

1
2
3

s2.txt 是:

7
8
9

D:\digit>echo s.txt s2.txt | python argpy.py
[1, 2, 3]
[7, 8, 9]

关键有两点:

  1. 使用 echo 代替 cat 以防止串联 更多学习链接:‘猫’之间的区别< file.txt' and 'echo < file.txt'

  2. 尝试通过拆分每个文件并存储在 args 中来读取每个新文件的 for 循环。 如何使用 sys.stdin 作为多个文本文件的输入来运行代码

快乐,因为我已经做到了:)

© www.soinside.com 2019 - 2024. All rights reserved.