使用 linux 命令输入字符串但输出错误

String input with wrong output using linux command

我创建了一个 python 程序,test.py,如下:

import subprocess
import sys, os
FolderPath = subprocess.getoutput("cd . && pwd")
ProgramName = sys.argv[0]
LogName = ProgramName[:-3]+'_printout.txt'
ProgramFile = FolderPath+'/'+ProgramName
LogFile = FolderPath+'/'+LogName

_stdin = sys.stdin
_stdout = sys.stdout
_stderr = sys.stderr

sys.stdin = open(LogFile, 'w')
sys.stdout = open(LogFile, 'a')
sys.stderr = open(LogFile, 'a')

Prog = open(ProgramFile, 'r')
print(Prog.read())

TEST = str(input("Enter the name: \n TEST_NAME: "))
print(TEST)

sys.stdin = _stdin.flush()
sys.stdout = _stdout.flush()
sys.stderr = _stderr.flush()

我在 linux 上使用命令 python test.py 执行后,我在 test_printout.txt 中得到了错误。

Enter the name: 
 TEST_NAME: Traceback (most recent call last):
  File "test.py", line 21, in <module>
    TEST = str(input("Enter the name: \n TEST_NAME: "))
io.UnsupportedOperation: not readable

我修改了代码:

import subprocess
import sys, os
FolderPath = subprocess.getoutput("cd . && pwd")
ProgramName = sys.argv[0]
LogName = ProgramName[:-3]+'_printout.txt'
ProgramFile = FolderPath+'/'+ProgramName
LogFile = FolderPath+'/'+LogName

_stdin = sys.stdin
_stdout = sys.stdout
_stderr = sys.stderr

sys.stdin = open(LogFile, 'w+')
sys.stdout = open(LogFile, 'a')
sys.stderr = open(LogFile, 'a')

Prog = open(ProgramFile, 'r')
print(Prog.read())

TEST = str(input("Enter the name: \n TEST_NAME: "))
print(TEST)

sys.stdin = _stdin.flush()
sys.stdout = _stdout.flush()
sys.stderr = _stderr.flush()

但是得到了:

Enter the name: 
 TEST_NAME: import subprocess

它不让我输入任何内容。我想要的是让我输入字符串,它也保存到 test_printout.txt.

Enter the name: 
 TEST_NAME: This Is What I Type And Save!

有人知道怎么解决吗?
此外,如果我使用 w+ 而不是 w 模式,如果我将程序更改为导入 pandas.DataFrame 并操作数据,则写入 test_printout.txt 将花费更长的时间。

有没有办法在不阅读整个内容的情况下只向 test_printout.txt 写入简单的打印字词?

更新
我修改了代码如下:

import subprocess, sys, os
FolderPath = subprocess.getoutput("cd . && pwd")
ProgramName = sys.argv[0]
LogName = ProgramName[:-3]+'_printout.txt'
ProgramFile = FolderPath+'/'+ProgramName
LogFile = FolderPath+'/'+LogName

_stdin = sys.stdin
_stdout = sys.stdout
_stderr = sys.stderr


class stdout_Logger(object):
    def __init__(self):
        self.stdout = sys.stdout
        self.log = open(LogFile, "a")

    def write(self, message):
        self.stdout.write(message)
        self.log.write(message)  

    def flush(self):
        #this flush method is needed for python 3 compatibility.
        #this handles the flush command by doing nothing.
        #you might want to specify some extra behavior here.
        pass    

sys.stdout = stdout_Logger()


class stderr_Logger(object):
    def __init__(self):
        self.stderr = sys.stderr
        self.log = open("test_printout.txt", "a")

    def write(self, message):
        self.stderr.write(message)
        self.log.write(message)  

    def flush(self):
        #this flush method is needed for python 3 compatibility.
        #this handles the flush command by doing nothing.
        #you might want to specify some extra behavior here.
        pass    

sys.stderr = stderr_Logger()

Prog = open(ProgramFile, 'r')
print(Prog.read())

##START Program

TEST = str(input("Enter the name: \n TEST_NAME: "))
print(TEST)

#END Program

sys.stdin = _stdin.flush()
sys.stdout = _stdout.flush()
sys.stderr = _stderr.flush()

这几乎是我想要的。这也将我的程序保存到顶部的 test_printout.txt 并在底部执行 print(TEST)
但是,它还会将所有程序打印到 linux 终端控制台,这不是我想要的。我只希望它在 linux 终端中打印 "Enter the name: \n TEST_NAME: " 并且我可以键入字符串而不是打印整个程序。
我认为问题来自 sys.stdin.

我想我明白了。问题是,当您在写入模式下用文件句柄替换输入时,您会禁止 input() 读取它。如果您尝试这样做,您可能会遇到同样的错误:

file = open("foo.txt",'w')
content = file.read()

绕过它的方法是记录流而不重定向它们。因此,您要么使用 python test.py > test_printout.txt 将控制台转储到文件,要么创建一个记录器 class 来环绕流(查看此答案:How to redirect stdout to both file and console with scripting?)。

也许您值得研究一下日志记录模块,因为我相信它可以相当巧妙地处理这些问题。

编辑:

根据您在评论中列出的内容,这就是您想要的:

import subprocess, sys, os
FolderPath = subprocess.getoutput("cd . && pwd")
ProgramName = sys.argv[0]
LogName = ProgramName[:-3]+'_printout.txt'
ProgramFile = FolderPath+'/'+ProgramName
LogFile = FolderPath+'/'+LogName

Prog = open(ProgramFile, 'r')
with open(LogFile, 'w') as logfile:
    logfile.write(Prog.read())

_stdin = sys.stdin
_stdout = sys.stdout
_stderr = sys.stderr

class stdout_Logger(object):
    def __init__(self):
        self.stdout = sys.stdout
        self.log = open(LogFile, "a")

    def write(self, message):
        self.stdout.write(message)
        self.log.write(message)  

    def flush(self):
        #this flush method is needed for python 3 compatibility.
        #this handles the flush command by doing nothing.
        #you might want to specify some extra behavior here.
        pass    


class stderr_Logger(object):
    def __init__(self):
        self.stderr = sys.stderr
        self.log = open("test_printout.txt", "a")

    def write(self, message):
        self.stderr.write(message)
        self.log.write(message)  

    def flush(self):
        #this flush method is needed for python 3 compatibility.
        #this handles the flush command by doing nothing.
        #you might want to specify some extra behavior here.
        pass    


sys.stdout = stdout_Logger()
sys.stderr = stderr_Logger()

##START Program

TEST = str(input("Enter the name: \n TEST_NAME: "))
print(TEST)

#END Program

sys.stdin = _stdin.flush()
sys.stdout = _stdout.flush()
sys.stderr = _stderr.flush()