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

问题描述

我创建了一个 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()

使用命令 linuxpython 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,'w+')
sys.stdout = open(LogFile,'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",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 将控制台转储到文件中,要么创建一个记录器类来环绕流(查看此答案: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",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()