简体   繁体   English

有什么方法可以增加 select() 在 Windows 上可以处理的最大文件描述符数量? _setmaxstdio 不影响它

[英]Is there any way to increase the maximum amount of file descriptors that select() can handle on Windows? _setmaxstdio doesn't affect it

For context, I'm writing an application in Python that needs to poll many hosts continuously, so I create a large number of sockets to communicate with those hosts.对于上下文,我正在 Python 中编写一个需要连续轮询许多主机的应用程序,因此我创建了大量 sockets 来与这些主机通信。 However, I can only create 511 sockets - when I try to create 512, I get a ValueError: too many file descriptors in select() .但是,我只能创建 511 sockets - 当我尝试创建 512 时,我得到一个ValueError: too many file descriptors in select() I thought this error was referencing the maximum amount of file descriptors that a process can have open at any given time, but when I try increasing that maximum with Python's win32file._setmaxstdio() , it has no effect - no matter what I set the limit to, I can only create 511 sockets.我认为这个错误引用了进程在任何给定时间可以打开的最大文件描述符数量,但是当我尝试使用 Python 的win32file._setmaxstdio()增加该最大值时,它没有任何效果 - 无论我设置什么限制到,我只能创建 511 sockets。 I even tried setting the limit to a value lower than 512 just to see if it would change anything, but I could still create 511 sockets, So as far as I can tell, the limits referenced by _setmaxstdio() and _getmaxstdio() are completely unrelated to the limit to how many sockets/file descriptors select() can handle.我什至尝试将限制设置为低于 512 的值只是为了看看它是否会改变任何东西,但我仍然可以创建 511 sockets,据我所知, _setmaxstdio()_getmaxstdio()引用的限制完全与select()可以处理的套接字/文件描述符的数量限制无关。

I tried investigating Python's select module to see if I could find where select() 's maximum is defined, or how to increase it.我尝试调查 Python 的select模块,看看是否可以找到select()的最大值在哪里定义,或者如何增加它。 Python's documentation for the select.select() function doesn't mention either of those things, but it does mention that select() comes from Windows' Winsock library. Python 的select.select() function 的文档没有提到这些,但它确实提到了select()来自 Windows 的 Winsock 库。 So I checked Microsoft's documentation of the select() function :所以我检查了微软的select() function 文档

Four macros are defined in the header file Winsock2.h for manipulating and checking the descriptor sets. header 文件 Winsock2.h 中定义了四个宏,用于操作和检查描述符集。 The variable FD_SETSIZE determines the maximum number of descriptors in a set.变量 FD_SETSIZE 决定了一组描述符的最大数量。 (The default value of FD_SETSIZE is 64 , which can be modified by defining FD_SETSIZE to another value before including Winsock2.h.) (FD_SETSIZE 的默认值为 64 ,可以通过在包含 Winsock2.h 之前将 FD_SETSIZE 定义为另一个值来修改。)

I read this to mean " select() can handle 64 sockets by default, but you can change that by altering the value of FD_SETSIZE before you include the header file".我读到这意味着“ select()默认可以处理 64 sockets,但您可以通过在包含 header 文件之前更改FD_SETSIZE的值来更改它”。 So I assume Python sets it to 512 before including the Winsock2 header file?所以我假设 Python 在包含 Winsock2 header 文件之前将其设置为 512? Or is select() 's limit set some other way?还是select()的限制以其他方式设置?

I just want to know where the select() function's limit is defined, how I can check it, and if it can be increased from within Python, but I'm clearly missing something fundamental here.我只想知道select()函数的限制在哪里定义,如何检查它,以及是否可以从 Python 中增加它,但我显然在这里遗漏了一些基本的东西。 select() can handle some number of file descriptors, and _setmaxstdio() is used to "[set] a maximum for the number of simultaneously open files at the stream I/O level", but changing the limit with _setmaxstdio() doesn't affect the limit for select() . select()可以处理一些文件描述符, _setmaxstdio()用于“[设置] stream I/O 级别同时打开的文件数量的最大值”,但使用_setmaxstdio()更改限制不会t 影响select()的限制。 Why not?为什么不? If select() isn't limited by the maximum amount of file descriptors you're allowed to have, then what is it limited by?如果select()不受您允许拥有的最大文件描述符数量的限制,那么它受什么限制?

A few days later, my best understanding of the situation is this: the per-process limit to number of file descriptors IS controlled by _setmaxstdio() , and I was using it correctly, BUT that upper limit set by _setmaxstdio() can and will be effectively hobbled to a separate, probably-lower limit if you're using the select() function, but if you instead use poll() , epoll() , etc., the limit you set with _setmaxstdio() will work just as you'd expect.几天后,我对这种情况的最佳理解是:每个进程对文件描述符数量的限制由_setmaxstdio()控制,我正确使用它,但是由_setmaxstdio()设置的上限可以并且将会如果您使用select() function,则可能会被有效地限制在一个单独的、可能的下限,但如果您改为使用poll()epoll()等,您使用_setmaxstdio()设置的限制将与你会期待的。 And if there is a way to increase the limits of the select() function, it seems like you need to mess around with the C runtime, which is something I don't know how to do.如果办法增加select() function 的限制,看起来你需要弄乱 C 运行时,这是我不知道该怎么做的事情。 Since I have the option to drop support for Windows and only support Unix instead, I'd much rather just do it that way.因为我可以选择放弃对 Windows 的支持,而只支持 Unix,所以我宁愿这样做。

If you're reading this answer because you want to increase the limits of Windows' select() function, and like me, you are new to the concept of file descriptors/completion ports, and haven't extensively worked with sockets before, and don't want to/don't know how to screw around with the C runtime (CRT), I suggest you first consider the following before continuing trying to alter the select() limit:如果您正在阅读此答案,因为您想增加 Windows 的select() function 的限制,并且像我一样,您是文件描述符/完成端口概念的新手,并且之前没有广泛使用 sockets,并且不想/不知道如何使用 C 运行时 (CRT),我建议您在继续尝试更改select()限制之前首先考虑以下内容:

  • Can you use poll() or epoll() instead of select() ?您可以使用poll()epoll()代替select()吗? In my case, the only reason I was using select() is because I was locked into because of the libraries I'm using - asyncio and psycopg.就我而言,我使用select()的唯一原因是因为我正在使用的库 - asyncio 和 psycopg 被锁定。 At the time of writing, psycopg does not support asyncio's ProactorEventLoop , so I was forced to instead use the SelectorEventLoop (which uses select() ) instead of the default ProactorEventLoop , which doesn't use select() .在撰写本文时,psycopg支持 asyncio 的ProactorEventLoop ,因此我被迫改用SelectorEventLoop (使用select() )而不是默认的ProactorEventLoop ,后者不使用select() However, psycopg has no such limitation in Unix - it will work with any asyncio event loop there.但是,psycopg 在 Unix 中没有这样的限制——它可以与那里的任何 asyncio 事件循环一起工作。 So if you can use poll() , epoll() , etc instead of select() , then that's probably a lot easier than trying to actually increase the select() limit since then you'll be able to just use _setmaxstdio() to set the file descriptor limit, and it'll actually let you have more file descriptors.因此,如果您可以使用poll()epoll()等代替select() ,那么这可能比尝试实际增加select()限制要容易得多,因为那时您就可以使用_setmaxstdio()来设置文件描述符限制,它实际上会让你有更多的文件描述符。

Instead of continuing to try to make this work with Windows, I'm just going to use Unix instead - I probably should have done that from the beginning since it's a backend kind of process, but the convenience of being able to run/test/debug the code directly on my development machine was tempting, and I thought that the added flexibility of supporting both Windows and Unix would be worth the (what I thought would be minimal) overhead of adding if os is Windows use SelectorEventLoop to the start of my application.与其继续尝试使用 Windows 进行这项工作,不如使用 Unix 代替 - 我可能应该从一开始就这样做,因为它是一种后端进程,但是能够运行/测试/的便利性直接在我的开发机器上调试代码很诱人,我认为支持 Windows 和 Unix 的额外灵活性是值得的(我认为这是最小的) if os is Windows use SelectorEventLoop的 start of mySelectorEvent 的开销(我认为这是最小的)添加到 SelectorEvent4应用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Windows中的select()python中的文件描述符过多 - too many file descriptors in select() python in windows 有没有办法在 PySimpleGui spinboxes 中限定 integer 输入范围的最小值和最大值,以便最小值不会超过最大值? - Is there any way to delimit minimum and maximum of an integer input range in PySimpleGui spinboxes, so that minimum doesn't surpases maximum? Python asyncio/aiohttp:ValueError:Windows 上的 select() 中的文件描述符太多 - Python asyncio/aiohttp: ValueError: too many file descriptors in select() on Windows mitmdump 错误:windows 中 select() 问题中的文件描述符过多 - mitmdump error: too many file descriptors in select() issue in windows python socket中select()可以管理多少个文件描述符? - how many file descriptors can select() manage in python socket? 有什么方法可以提高关闭文件的速度吗? - Any way to increase speed of closing a file? combine_first 似乎没有任何影响 dataframe - combine_first doesn't seems to have any affect dataframe 在Python中操作select.select的文件描述符 - Manipulate File Descriptors for select.select in Python MariaDB - 插入值不会影响任何行 - MariaDB - Inserting Values doesn't affect any rows 无法在Windows中处理字符串 - Can't handle strings in windows
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM