Hello, first thing to say -> Great work !
I have tried to setup a demo ftpd server using the library and everything works as I want (I know the sample code here is missing a few things, but I have tried to track it down):
import os
import sys
import time
import threading
import logging.handlers
from pyftpdlib.log import logger, LogFormatter
from pyftpdlib._compat import b, unicode
from pyftpdlib.filesystems import AbstractedFS
from pyftpdlib.servers import ThreadedFTPServer
from pyftpdlib.handlers import FTPHandler, TLS_FTPHandler
from pyftpdlib.authorizers import DummyAuthorizer, AuthenticationFailed
class MyHandler(FTPHandler):
def on_disconnect(self):
pass
class MyTLSHandler(TLS_FTPHandler):
def on_disconnect(self):
pass
class test_ftpd(threading.Thread):
handler = None
server_class = ThreadedFTPServer
def __init__(self):
threading.Thread.__init__(self)
self.__serving = False
self.__lock = threading.Lock()
self.__flag = threading.Event()
channel = logging.handlers.RotatingFileHandler('./test_ftpd.log', maxBytes=1024, backupCount=6)
channel.setFormatter(LogFormatter())
logger = logging.getLogger('pyftpdlib')
logger.addHandler(channel)
logger.setLevel(logging.INFO)
ftpd_usetls = 0
authorizer = DummyAuthorizer()
if not ftpd_usetls:
self.handler = MyHandler
else:
self.handler = MyTLSHandler
self.handler.certfile = './test_ftpd.pem'
self.handler.authorizer = authorizer
self.handler.abstracted_fs = AbstractedFS
self.handler.banner = "test ftpd ready."
self.server = self.server_class(('0.0.0.0', 21), self.handler)
@property
def running(self):
return self.__serving
def start(self, timeout=0.001):
if self.__serving:
raise RuntimeError("Server already started")
self.__timeout = timeout
threading.Thread.start(self)
self.__flag.wait()
def run(self):
self.__serving = True
self.__flag.set()
self.server._log_start()
while self.__serving:
self.__lock.acquire()
self.server.serve_forever(timeout=self.__timeout, blocking=False)
self.__lock.release()
logger.info(">>> shutting down FTP server (%s active fds) <<<", self.server._map_len())
self.server.close_all()
def stop(self):
if not self.__serving:
raise RuntimeError("Server not started yet")
self.__serving = False
self.join(timeout=10)
if threading.activeCount() > 1:
def main(argv):
server = test_ftpd()
server.start()
while server.running:
try:
time.sleep(1.0)
except KeyboardInterrupt:
server.stop()
if __name__ == '__main__':
main(sys.argv[1:])
Then I tried to compile with py2exe:
#!/usr/bin/python3
# -*- coding: utf-8 -*-
from distutils.core import setup
import py2exe
class Target(object):
'''Target is the baseclass for all executables that are created.
It defines properties that are shared by all of them.
'''
def __init__(self, **kw):
self.__dict__.update(kw)
# the VersionInfo resource, uncomment and fill in those items
# that make sense:
# The 'version' attribute MUST be defined, otherwise no versioninfo will be built:
# self.version = "1.0"
self.company_name = "Test"
self.copyright = "Copyright Test © 2014"
# self.legal_copyright = "Copyright Company Name © 2013"
# self.legal_trademark = ""
# self.product_version = "1.0.0.0"
self.product_name = "test FTP server"
# self.private_build = "foo"
# self.special_build = "bar"
def copy(self):
return Target(**self.__dict__)
def __setitem__(self, name, value):
self.__dict__[name] = value
test_ftpd = Target(
# We can extend or override the VersionInfo of the base class:
version = "1.0",
# file_description = "File Description",
# comments = "Some Comments",
# internal_name = "spam",
script="test.py", # path of the main script
# Allows to specify the basename of the executable, if different from 'test'
# dest_base = "test",
# Icon resources:[(resource_id, path to .ico file), ...]
# icon_resources=[(1, r"test.ico")]
)
py2exe_options = dict(
packages = [],
## excludes = "tof_specials Tkinter".split(),
## ignores = "dotblas gnosis.xml.pickle.parsers._cexpat mx.DateTime".split(),
## dll_excludes = "MSVCP90.dll mswsock.dll powrprof.dll".split(),
optimize=2,
compressed=True, # uncompressed may or may not have a faster startup
bundle_files=0,
dist_dir='dist_test',
)
setup(name="name",
# console based executables
console=[test_ftpd],
# py2exe options
zipfile=None,
options={"py2exe": py2exe_options},
)
The compile is ok and I get the exe, but when I try to start it I get the following error:
Traceback (most recent call last):
File "test.py", line 13, in <module>
ImportError: cannot import name 'TLS_FTPHandler'
What is going wrong here ?
My System:
Windows 7 64 Bit
Python 3.4.1 64 Bit
py2exe for python 3