【问题标题】:Inexplicable ResourceWarning: unclosed file <_io.TextIOWrapper name=3莫名其妙的资源警告:未关闭的文件 <_io.TextIOWrapper name=3
【发布时间】:2018-07-01 15:43:47
【问题描述】:

我正在完成将我的代码从 python2.7 移动到 python3.5 并打开 warnings 以检查另一个模块。
使用os.popen() 时出现以下错误。

ResourceWarning: unclosed file <_io.TextIOWrapper name=3 encoding='UTF-8'>

上例“name=3”中的数字会根据代码发生变化,但始终是整数。
这段代码 sn -p 产生错误,但没有打开文件,这与错误消息 unclosed file 完全冲突。
我的环境是使用python 3.5.2的Linux

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-
import warnings
import os
warnings.simplefilter('default')
sink_list = os.popen('pacmd list-sinks | grep "name:" | cut --delimiter=: -f2').readlines()
print (sink_list)
sink = os.popen('pacmd list | grep "Default sink name" | cut --delimiter=: -f2').readline()
print(sink)

结果如下:

test.py:6: ResourceWarning: unclosed file <_io.TextIOWrapper name=3 encoding='UTF-8'>
  sink_list = os.popen('pacmd list-sinks | grep "name:" | cut --delimiter=: -f2').readlines()
[' <alsa_output.pci-0000_00_1b.0.analog-stereo>\n', ' <fs2-Equaliser>\n', ' <fs2-bs2b>\n']
test.py:8: ResourceWarning: unclosed file <_io.TextIOWrapper name=3 encoding='UTF-8'>
  sink = os.popen('pacmd list | grep "Default sink name" | cut --delimiter=: -f2').readline()
 fs2-Equaliser

有谁知道为什么会发出这个警告,尤其是在这种情况下,没有文件被打开?

【问题讨论】:

    标签: python python-3.x warnings popen


    【解决方案1】:

    整数是一个文件描述符,操作系统用来谈论分配给进程的文件句柄的整数。 012stdinstdoutstderr,3 及以上是使用的更多文件描述符。

    您收到资源警告是因为您打开了文件句柄,但从未明确关闭它。您只需在 Python 文件对象包装器上调用 .readlines().readline()

    sink_list = os.popen('pacmd list-sinks | grep "name:" | cut --delimiter=: -f2').readlines()
    

    这会使文件对象被垃圾收集器关闭,并且您会收到警告。您可以将打开的对象用作上下文管理器来为您关闭它:

     with os.popen('pacmd list-sinks | grep "name:" | cut --delimiter=: -f2') as list_sinks:
        sink_list = list_sinks.readlines()
    

    就个人而言,我会使用subprocess module 来处理外部进程,并使用Python 来进行行选择。这可以让您避免启动单独的sh 进程,并且通常具有更好的异常处理:

    import subprocess
    
    # read list of sinks
    result = suprocess.run(['pacmd', 'list-sinks'], stdout=subprocess.STDOUT, encoding='UTF-8')
    sink_list = [l.split(':', 2) for l in result.stdout if 'name:' in l]
    
    # read default sink
    result = suprocess.run(['pacmd', 'list'], stdout=subprocess.STDOUT, encoding='UTF-8')
    default_sink = next((l.split(':', 2) for l in result.stdout if 'Default sink name' in l), None)
    

    【讨论】:

    • 太棒了,它正盯着我的脸!问候。
    猜你喜欢
    • 2018-11-18
    • 2012-05-19
    • 1970-01-01
    • 1970-01-01
    • 2011-08-30
    • 1970-01-01
    • 2013-04-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多