代码之家  ›  专栏  ›  技术社区  ›  Rolf of Saxony

无法解释的资源警告:未关闭的文件<\u io.textiowrapper name=3

  •  0
  • Rolf of Saxony  · 技术社区  · 6 年前

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

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

    上面示例“name=3”中的数字将根据代码而改变,但它始终是整数。
    此代码段产生错误,但尚未打开与错误消息完全冲突的文件 unclosed file .
    我的环境是Linux,使用python 3.5.2

    #!/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
    

    是否有人知道为什么发出此警告,特别是在没有打开文件的情况下?

    1 回复  |  直到 6 年前
        1
  •  3
  •   Martijn Pieters    6 年前

    整数是一个 文件描述符 ,操作系统用来讨论分配给进程的文件句柄的整数。 0 ,请 1 2 stdin ,请 stdout stderr ,3和以上是进一步使用的文件描述符。

    您会收到资源警告,因为您打开了文件句柄,但从不显式关闭它。你只要打电话 .readlines() .readline() 在python文件对象包装器上:

    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)