我在StackOverflow和其他网站上搜索过,但我发现一些方法可以重定向print语句直接输出到文件,但我希望程序正常工作,将输出显示到控制台,然后在程序完成所有操作后保存其内容。
如果有影响,我正在使用Python2.7的PyCharm。
好的,通常为了完成这个任务,您需要重写Python内置函数print
。但是...有一个叫做iPython的工具可以提供一些钩子。
首先您需要安装iPython
:
#bash
sudo pip install ipython
我使用sudo命令来简单地定位需要到达的文件夹,继续阅读以下内容。
安装ipython后,你将拥有ipython扩展文件夹,因此进入它:
#bash
cd ~/.ipython/extensions/
在那里创建一个名为print_to_file.py
的文件,下面是它的内容:
#python
class PrintWatcher(object):
def __init__(self, ip):
self.shell = ip
def post_execute(self):
with open('/home/turkus/shell.txt', 'a+') as f:
in_len = len(self.shell.user_ns['In'])
i = in_len - 1
in_ = self.shell.user_ns['In'][i]
out = self.shell.user_ns['Out'].get(i, '')
# you can edit this line if you want different input in shell.txt
f.write('{}\n{}\n'.format(in_, out))
def load_ipython_extension(ip):
pw = PrintWatcher(ip)
ip.events.register('post_run_cell', pw.post_execute)
保存文件后,只需运行:
#bash
ipython profile create
# you will get something like that:
[ProfileCreate] Generating default config file: u'/home/turkus/.ipython/profile_default/ipython_config.py'
现在回到设置我们的钩子。我们必须打开上面路径下创建的ipython_config.py
文件,并在其中添加一些魔法(文件中有很多内容,所以请到文件末尾):
# some commented lines here
c = get_config()
c.InteractiveShellApp.extensions = [
'print_to_file'
]
ipython
并编写您的代码。您的每个输入都将被写入到您上面提供路径下的文件中,在我的情况下是:/home/turkus/shell.txt
注释
你可以通过从 ipython_config.py
文件中的 c.InteractiveShellApp.extensions
列表中删除 'print_to_file'
来避免在每次启动 ipython
时加载扩展。但是请记住,你仍然可以随时加载它,只需在 ipython
控制台中键入:
➜ ~ ipython
Python 2.7.12 (default, Jul 1 2016, 15:12:24)
Type "copyright", "credits" or "license" for more information.
IPython 4.0.0 -- An enhanced Interactive Python.
? -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help -> Python's own help system.
object? -> Details about 'object', use 'object??' for extra details.
In [1]: %load_ext print_to_file
print_to_file.py
中的任何更改都会在使用 %reload_ext print_to_file
命令后反映在打开的 IPython shell 中,因此您无需退出并再次启动。
python script.py >> shell.txt
,它将每个打印输出到一个文件中,但不在控制台中显示。 - turkusprint()
语句替换为.write
,可以轻松实现此目标。class Writer(object):
def __init__(self, out_file, overwrite=False):
self.file_name = out_file
self.overwrite = overwrite
self.history = []
def write(self, statement):
self.history.append(statement)
print statement
def close(self):
if self.overwrite:
self.out_file = open(self.file_name, 'wb')
else:
self.out_file = open(self.file_name, 'ab')
for x in self.history:
self.out_file.write(x+'/n')
self.out_file.close()
self.history = []
p = Writer('my_output_file.txt')
p.write('my string to print and save!')
p.close() #close the writer to save the contents to a file before exiting
python your_program | tee output.txt
import builtins
f = open("logs.txt", "w")
def print(*args, sep=' ', end='\n', **kwargs):
builtins.print(*args, sep=sep, end=end, **kwargs)
f.write(sep.join(*args) + end)
编辑:Python 2的类似解决方案
from __future__ import print_function
class Print:
def __init__(self, print_function, filename='test', mode='w'):
self.print_function = print_function
self.file = open(filename, 'w')
def __call__(self, *args, **kwargs):
self.print_function(*args, **kwargs)
kwargs['file'] = self.file
self.print_function(*args, **kwargs)
print = Print(print, 'logs.txt')
print
函数,您可以像从__future__
导入的函数一样使用它。print.file.close()
import future_builtins as builtins
,然后我写了你的def print...
,但是出现了几个错误!我不知道如何应用你的解决方案。非常感谢您能进一步解释一下... - Mohammad ElNesrfuture_builtins
模块不包括打印函数。我认为在Python 2中唯一的解决方案是创建一个函数,并在每次想要使用print
时调用此函数。 - odrlingprint statement
logger += statement+"\n" #a new line char so each statement is on a new line
with open('file.txt', 'a') as f:
f.write(statement)
感谢所有对这个问题做出贡献的人。我最终发现了一个解决方案,只需对原始代码进行最小修改。该解决方案由成员@Status提供,这是它的链接。
虽然在发布问题之前我进行了很多搜索,但尊敬的成员的回答使我能够进行精确搜索,特别是@turkus的贡献非常杰出和@Glostas让我认识到“tee”,它指引我找到了我发布的解决方案(尽管它不包括“tee”)。
解决方案,在提到的帖子上进行了轻微修改:
1- 在程序中添加以下类:
class Logger(object):
"""
Lumberjack class - duplicates sys.stdout to a log file and it's okay
source: https://dev59.com/gHRB5IYBdhLWcg3wc3A0#24583265
"""
def __init__(self, filename="Red.Wood", mode="a", buff=0):
self.stdout = sys.stdout
self.file = open(filename, mode, buff)
sys.stdout = self
def __del__(self):
self.close()
def __enter__(self):
pass
def __exit__(self, *args):
pass
def write(self, message):
self.stdout.write(message)
self.file.write(message)
def flush(self):
self.stdout.flush()
self.file.flush()
os.fsync(self.file.fileno())
def close(self):
if self.stdout != None:
sys.stdout = self.stdout
self.stdout = None
if self.file != None:
self.file.close()
self.file = None
2- 在程序开头,在任何打印语句之前,加入以下代码:
my_console = Logger('my_console_file.txt') # you can change the file's name
3- 在程序结束时,在所有的打印语句之后,加入这一行:
my_console.close()
我测试过了,它完美地运行了,最后在程序结束后,我有了一个控制台输出的克隆。
向大家致以最诚挚的问候,并对所有贡献者表示衷心的感谢。
有一个非常明显但不太优雅的解决方案。
而不是:
print statement 1
calculation
print statement 2
你可以做出类似的东西
sexport =''
calculation
print statement 1
sexport += statement1 + "\n"
calculaztion
print statement 2
sexport += statement 2
最后将s导出保存到文件中