Python中select.select()文件句柄的问题

背景

python中的select.select()函数调用了系统底层的select(),但是他有一个限制,就是当打开的文件句柄的数字达到1024后,就会出现下面的错误

ValueError: filedescriptor out of range in select()

原理分析

这个值在select()中对应的是FD_SETSIZE,下面我们写一段脚步来证明

#!/usr/bin/env python

import subprocess

import os

import select

import getpass

host = 'example.com'

timeout = 5

password = getpass.getpass(prompt="Enter your password:")

for i in range(1000):

        (rfd, wfd) = os.pipe()

        ssh_cmd = ['sshpass', '-d%d ' % rfd]

        ssh_cmd += ['ssh', '%s' % host, 'uptime']

        print ssh_cmd

        os.write(wfd, password + '\n')

        p = subprocess.Popen(ssh_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)

        rfd, wfd, efd = select.select([p.stdout, p.stderr], [], [p.stderr], timeout)

        if rfd:

                print p.stdout.read()

                print p.stderr.read()

相关的原理解析还可以参考:

https://github.com/ansible/ansible/issues/10157

https://issues.apache.org/jira/browse/QPID-5588

https://github.com/ansible/ansible/issues/14143

 

### Python句柄的使用及其相关问题Python 编程中,“句柄”通常指的是操作系统资源的一个抽象表示,比如文件描述符、窗口对象或者数据库连接等。这些句柄可以被看作是对底层资源的一种引用或指针。 #### 文件句柄 文件句柄Python 中最常见的句柄形式之一。通过 `open()` 函数创建文件对象时,实际上是在操作系统的帮助下分配了一个文件句柄[^1]。以下是打开文件并读取其内容的基本示例: ```python with open('example.txt', 'r') as file_handle: content = file_handle.read() print(content) ``` 在这个例子中,`file_handle` 是一个文件句柄,它允许程序访问磁盘上的实际文件数据。当上下文管理器 (`with`) 结束时,文件句柄会被自动关闭以释放资源。 #### Windows API 句柄 对于运行在 Windows 平台下的应用程序来说,可能还需要处理来自 WinAPI 的各种句柄类型,例如进程句柄、线程句柄以及窗口句柄等等。这可以通过第三方库如 PyWin32 来实现交互[^4]。下面展示如何获取当前活动窗口的句柄: ```python import win32gui hwnd = win32gui.GetForegroundWindow() # 获取前台窗口的句柄 text = win32gui.GetWindowText(hwnd) # 使用该句柄来检索窗口标题文字 print(f'Active window title: {text}') ``` 这里需要注意的是,在多线程环境中操作某些类型的句柄可能会受到全局解释器锁(GIL)[^2]的影响,这意味着即使有多个物理核心可用,同一时刻也只能有一个线程执行 Python 字节码。 #### 数据库连接作为句柄 除了文件和系统级别的句柄外,数据库连接也可以视为一种高级别的句柄。建立到 MySQL 或 PostgreSQL 等关系型数据库服务器的链接本质上就是请求远程服务端返回给客户端一个唯一的会话标识——即所谓的“连接句柄”。以下是如何利用 SQLAlchemy 创建引擎并与 SQLite 数据库存储进行通信的例子: ```python from sqlalchemy import create_engine engine = create_engine('sqlite:///mydatabase.db') connection = engine.connect() result_set = connection.execute("SELECT * FROM users;") for row in result_set: print(row) connection.close() ``` 在这里,变量 `connection` 就代表了指向本地 SQLite 数据库实例的一条专用通道或者说句柄。 ### 解决与句柄有关的问题 如果遇到诸如“Too many open files”的错误提示,则表明你的应用未能妥善地管理和释放已使用的句柄资源。确保每次调用完相应的方法之后都要显式地关闭它们;另外还可以考虑增加超时设置或是采用更高效的并发模型(如异步IO),从而减少不必要的阻塞等待时间。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值