我在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()您能知道为什么这段代码在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发布于 2017-08-02 18:20:37
好的,很显然,Mac中的坏文件描述符是众所周知的:
如果在分叉之前创建一个IOLoop,然后尝试在子进程中使用它,就会发生这种情况。如果要使用叉,则必须在创建单例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()https://stackoverflow.com/questions/45438323
复制相似问题