Python Errno 9 Mac OS X 中的错误文件描述符
Python Errno 9 Bad file descriptor in Mac OS X
我有以下代码 运行ning 多次后没有任何问题
彼此在 Linux:
def test_ftp(ftpserver):
with FTP() as f:
f.connect("localhost", port=ftpserver.server_port)
f.login("M1", "bachmann")
f.cwd("/")
f.mkd("FOO")
f.quit()
相同的测试在 MacOS X 中只能 运行 一次,之后它就会挂起。重启机器,是我重新运行测试的唯一方法。
ftpserver
是在pytest-localftpserver中定义的一个测试夹具,我把这个夹具的代码贴在这里是因为我怀疑它是错误的原因:
class MPFTPServer(multiprocessing.Process):
def __init__(self, username, password, ftp_home, ftp_port, **kwargs):
self._server = SimpleFTPServer(username, password, ftp_home, ftp_port)
self.server_home = self._server.ftp_home
self.anon_root = self._server.anon_root
self.server_port = self._server.ftp_port
super().__init__(**kwargs)
def run(self):
self._server.serve_forever()
def join(self):
self._server.stop()
def stop(self):
self._server.stop()
@pytest.fixture(scope="session", autouse=True)
def ftpserver(request):
"""The returned ``ftpsever`` provides a threaded instance of
``pyftpdlib.servers.FTPServer`` running on localhost.
...
"""
from pytest_localftpserver.plugin import MPFTPServer
ftp_user = os.getenv("FTP_USER", "fakeusername")
ftp_password = os.getenv("FTP_PASS", "qweqwe")
ftp_home = os.getenv("FTP_HOME", "")
ftp_port = int(os.getenv("FTP_PORT", 0))
server = MPFTPServer(ftp_user, ftp_password, ftp_home, ftp_port)
# This is a must in order to clear used sockets
server.daemon = True
server.start()
yield server
server.join()
你能说出为什么这段代码 "works repeatedly" 在 Linux 而不是在 MacOSX 中吗?
更新
进一步挖掘,我发现 ftp 服务器甚至不会启动,因此挂起。代码崩溃并显示以下消息:
Process MPFTPServer-1:
Traceback (most recent call last):
File "/opt/pkg/lib/python3.5/multiprocessing/process.py", line 249, in _bootstrap
self.run()
File "/Users/w/.virtualenvs/controller_config/lib/python3.5/site-packages/pytest_localftpserver/plugin.py", line 81, in run
self._server.serve_forever()
File "/Users/w/.virtualenvs/controller_config/lib/python3.5/site-packages/pyftpdlib/servers.py", line 207, in serve_forever
self.ioloop.loop(timeout, blocking)
File "/Users/w/.virtualenvs/controller_config/lib/python3.5/site-packages/pyftpdlib/ioloop.py", line 348, in loop
poll(soonest_timeout)
File "/Users/w/.virtualenvs/controller_config/lib/python3.5/site-packages/pyftpdlib/ioloop.py", line 709, in poll
timeout)
OSError: [Errno 9] Bad file descriptor
好的,显然 bad file descriptor in Mac OS X 是已知的:
that's what happens if you create an IOLoop before a fork and
then try to use it in the child process. If you're going to use fork,
you have to do it before anything creates the singleton IOLoop.
所以解决方案只是在 run
方法中启动服务器实例,而不是在 __init__
:
中
class MPFTPServer(multiprocessing.Process):
def __init__(self, username, password, ftp_home, ftp_port, **kwargs):
self.username = username
self.password = password
self.server_home = ftp_home
self.server_port = ftp_port
super().__init__(**kwargs)
def run(self):
self._server = SimpleFTPServer(self.username, self.password,
self.server_home, self.server_port)
self._server.serve_forever()
我有以下代码 运行ning 多次后没有任何问题 彼此在 Linux:
def test_ftp(ftpserver):
with FTP() as f:
f.connect("localhost", port=ftpserver.server_port)
f.login("M1", "bachmann")
f.cwd("/")
f.mkd("FOO")
f.quit()
相同的测试在 MacOS X 中只能 运行 一次,之后它就会挂起。重启机器,是我重新运行测试的唯一方法。
ftpserver
是在pytest-localftpserver中定义的一个测试夹具,我把这个夹具的代码贴在这里是因为我怀疑它是错误的原因:
class MPFTPServer(multiprocessing.Process):
def __init__(self, username, password, ftp_home, ftp_port, **kwargs):
self._server = SimpleFTPServer(username, password, ftp_home, ftp_port)
self.server_home = self._server.ftp_home
self.anon_root = self._server.anon_root
self.server_port = self._server.ftp_port
super().__init__(**kwargs)
def run(self):
self._server.serve_forever()
def join(self):
self._server.stop()
def stop(self):
self._server.stop()
@pytest.fixture(scope="session", autouse=True)
def ftpserver(request):
"""The returned ``ftpsever`` provides a threaded instance of
``pyftpdlib.servers.FTPServer`` running on localhost.
...
"""
from pytest_localftpserver.plugin import MPFTPServer
ftp_user = os.getenv("FTP_USER", "fakeusername")
ftp_password = os.getenv("FTP_PASS", "qweqwe")
ftp_home = os.getenv("FTP_HOME", "")
ftp_port = int(os.getenv("FTP_PORT", 0))
server = MPFTPServer(ftp_user, ftp_password, ftp_home, ftp_port)
# This is a must in order to clear used sockets
server.daemon = True
server.start()
yield server
server.join()
你能说出为什么这段代码 "works repeatedly" 在 Linux 而不是在 MacOSX 中吗?
更新
进一步挖掘,我发现 ftp 服务器甚至不会启动,因此挂起。代码崩溃并显示以下消息:
Process MPFTPServer-1:
Traceback (most recent call last):
File "/opt/pkg/lib/python3.5/multiprocessing/process.py", line 249, in _bootstrap
self.run()
File "/Users/w/.virtualenvs/controller_config/lib/python3.5/site-packages/pytest_localftpserver/plugin.py", line 81, in run
self._server.serve_forever()
File "/Users/w/.virtualenvs/controller_config/lib/python3.5/site-packages/pyftpdlib/servers.py", line 207, in serve_forever
self.ioloop.loop(timeout, blocking)
File "/Users/w/.virtualenvs/controller_config/lib/python3.5/site-packages/pyftpdlib/ioloop.py", line 348, in loop
poll(soonest_timeout)
File "/Users/w/.virtualenvs/controller_config/lib/python3.5/site-packages/pyftpdlib/ioloop.py", line 709, in poll
timeout)
OSError: [Errno 9] Bad file descriptor
好的,显然 bad file descriptor in Mac OS X 是已知的:
that's what happens if you create an IOLoop before a fork and then try to use it in the child process. If you're going to use fork, you have to do it before anything creates the singleton IOLoop.
所以解决方案只是在 run
方法中启动服务器实例,而不是在 __init__
:
class MPFTPServer(multiprocessing.Process):
def __init__(self, username, password, ftp_home, ftp_port, **kwargs):
self.username = username
self.password = password
self.server_home = ftp_home
self.server_port = ftp_port
super().__init__(**kwargs)
def run(self):
self._server = SimpleFTPServer(self.username, self.password,
self.server_home, self.server_port)
self._server.serve_forever()