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

How to read two different files in Python by sys.stdin

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

当我在 cmd win 10 和 python 3.6 上 运行 下面的代码时:

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 吗? 我使用了下面的,但其中 none 个是答案:

sys.stdin.close()
sys.stdin = sys.__stdin__ 
sys.stdout.flush() 

在此先感谢您的帮助。

让我试着解释一下。

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

只有 1 个输出,没有 2 个。它的作用 'streams' file1 的内容到 stdout 然后 'streams' [=18= 的内容] 到 stdout没有任何暂停或分隔符!!

所以只有 1 'stream' 个输出,然后您使用 | 重定向到你的 pyton 脚本:

| pytest.py

因此 pytest.py 将收到 1 'stream' 个输入,它不知道更好或更多。

如果想按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 module for reading and writing csv files

[根据评论编辑:]

I could read multiple files it by pandas "pd.read_csv" , but my problem is how can I do it by sys.stdin?

你真的应该质疑为什么你如此专注于使用 stdin。从 python 脚本中读取它可能会更有效。

如果您必须使用 stdin,那么您可以在 python、header、页脚、分隔符之外部署各种。一旦你定义了它并且能够这样做,那么你可以更改 python 中的代码以根据从 stdin 接收到的 header/footer/separator 执行各种功能。

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

[根据评论编辑:]

I want to load these files I Hadoop ecosystem and I am using Hadoop streaming for that

不知何故,您需要 "signal" 您的 python 脚本,它正在处理一个包含新信息的新文件。

假设你有 2 个文件,第一行需要是某种 "header" 指示文件,以及需要对其余数据执行哪个函数,直到一个新的 "header"已收到。

所以假设您的 "train" 数据以行 @is_train@ 为前缀,而您的 "test" 数据以行 @is_test@

为前缀

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

现在重定向到 stdin 将在数据之前发送这两个 header。您可以让 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)

正如您在代码中看到的,您还需要一个 "footer" 来确定数据何时结束,在本例中选择了 @stop@

发送 header/footers 的一种方式可以是:

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

和三个额外的文件,只包含适当的 header 或页脚

另一个解决方案是:

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 以防止连接 link 学习更多:Difference between 'cat < file.txt' and 'echo < file.txt'

  2. 通过拆分每个文件并存储在 args 中,尝试为每个新文件读入 for 循环。 How to run code with sys.stdin as input on multiple text files

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