莫名其妙的 ResourceWarning:未关闭的文件 <_io.TextIOWrapper name=3
Inexplicable ResourceWarning: unclosed file <_io.TextIOWrapper name=3
我正在完成将我的代码从 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
有谁知道为什么会发出这个警告,尤其是在这种没有文件被打开的情况下?
整数是 文件描述符 ,OS 用来讨论分配给进程的文件句柄的整数。 0
、1
和 2
是 stdin
、stdout
和 stderr
,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)
我正在完成将我的代码从 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
有谁知道为什么会发出这个警告,尤其是在这种没有文件被打开的情况下?
整数是 文件描述符 ,OS 用来讨论分配给进程的文件句柄的整数。 0
、1
和 2
是 stdin
、stdout
和 stderr
,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)