【问题标题】:how to close sys.stdout in a nested loop so that it doesnt copy print statements outside inner loop in file如何在嵌套循环中关闭 sys.stdout,以便它不会在文件中的内部循环之外复制打印语句
【发布时间】:2018-03-16 18:45:36
【问题描述】:

我是 python 3 的新手,我正在研究推文的情绪分析。我的代码以一个 for 循环开始,它接收 50 条推文,我对其进行清理和预处理。在此之后(仍在 for 循环内)我想将每条推文保存在一个文本文件中(每条推文都在一个新行上) 代码如下:

    for loop:
        ..
        print statments
        ..
        if loop:
            filename=open("withnouns.txt","a")
            sys.stdout = filename
            print(new_words)#tokenised tweet that i want to save in txt file
            print("\n")
            sys.stdout.close()#i close it because i dont want to save print statements OUTSIDE if loop to be saved in txt file
        ..
        ..
        print statements

运行后显示错误:第 71 行关闭文件的 I/O 操作(if 循环后的第一个打印语句)

我的问题是,有什么方法可以暂时关闭然后打开 sys.stdout 并使其仅在 if 循环内处于活动状态?

【问题讨论】:

标签: python python-3.x file-handling sentiment-analysis


【解决方案1】:

您根本不需要分配给sys.stdout。只需告诉print() 改为写入文件,使用file 参数:

print(new_words, file=filename)
print("\n", file=filename)

现在无需为sys.stdout 分配任何内容,因为现在print() 直接写入您的文件。

您还想将文件对象用作上下文管理器,因此将其关闭或者您:

with open("withnouns.txt","a") as filename:
    print(new_words, file=filename)
    print("\n", file=filename)

无论如何,您都不需要关闭 sys.stdout 引用,而是想关闭 filename,并将 sys.stdout 恢复到以前的状态。

如果您确实需要替换 sys.stdout,您有几个选项,从最正确到最不正确:

  • 使用contextlib.redirect_stdout():

    import contextlib
    
    with contextlib.redirect_stdout(some_fileobject):
        # do things that write to stdout
    

    在块的末尾stdout 已为您修复。

  • 先手动存储sys.stdout

    old_stdout = sys.stdout
    sys.stdout = new_object
    try:
        # do things that write to stdout
    finally:
        sys.stdout = old_stdout
    
  • 使用sys.__stdout__ copy;这是在启动时设置的:

    sys.stdout = new_object
    try:
        # do things that write to stdout
    finally:
        sys.stdout = sys.__stdout__
    

    您需要考虑到sys.stdout 在您的代码运行之前可能已被其他内容替换,并且将其恢复为sys.__stdout__ 可能是错误的做法。

【讨论】:

  • 非常感谢我现在明白了!我不知道根本不需要使用 sys.stdout。对不起我的无知。
【解决方案2】:

我不确定这是否正是你想要做的,但你可以改变它

filename=open("withnouns.txt","a")
sys.stdout = filename
print(new_words)
print("\n")
sys.stdout.close()

filename=open("withnouns.txt","a")
filename.write(new_words + "\n")
filename.write("\n\n")
filename.close()

或者,你可以从sys.__stdout__获取sys.stdout的原始值,这样你的代码就变成了

filename=open("withnouns.txt","a")
sys.stdout = filename
print(new_words)
print("\n")
filename.close()
sys.stdout = sys.__stdout__

【讨论】:

  • print() 添加一个换行符,所以print(new_words)print(\n')` 将产生三个换行符,而您的write() 调用只会产生一个换行符。
  • @MartijnPieters 甚至没有想到这一点!不好解决
【解决方案3】:

您混淆了两种不同的文件写入方式。

sys.stdout 将您的输出通过管道传输到控制台/终端。这可以写入文件,但它非常迂回。

写入文件是不同的。在 python 中,如果你正在编写长度相同的值列表,你应该查看csv module(也许即使你不是,它也很容易使用)。

在循环外打开您的文件。在循环中,逐行写入文件。关闭循环外的文件。如果您使用以下“with”语法,这将自动为您完成:

import csv
with open('file.csv') as f:
    writer = csv.writer(f, delimiter=',', quotechar='|', quoting=csv.QUOTE_MINIMAL)

    for loop:
        # tokenize tweet
        writer.writerow(tweet)

或者,循环遍历标记化推文并将其保存到列表列表中。然后,在循环之外和循环之后,将整个内容写入文件:

import csv
tweets = []
for loop:
    # tokenize tweet
    tweets.append(tweet)

with open('file.csv') as f:
    writer = csv.writer(f, delimiter=',', quotechar='|', quoting=csv.QUOTE_MINIMAL)
    writer.writerows(tweets)

【讨论】:

  • 哦,是的,我能做到!谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-22
  • 1970-01-01
  • 1970-01-01
  • 2021-02-04
相关资源
最近更新 更多