{"id":13502258,"url":"https://github.com/giampaolo/pyftpdlib","last_synced_at":"2025-11-12T21:36:51.800Z","repository":{"id":648916,"uuid":"20262870","full_name":"giampaolo/pyftpdlib","owner":"giampaolo","description":"Extremely fast and scalable Python FTP server library","archived":false,"fork":false,"pushed_at":"2025-11-12T07:53:16.000Z","size":4269,"stargazers_count":1791,"open_issues_count":136,"forks_count":274,"subscribers_count":49,"default_branch":"master","last_synced_at":"2025-11-12T21:36:46.997Z","etag":null,"topics":["asynchronous","ftp","ftp-server","ftps","python"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/giampaolo.png","metadata":{"files":{"readme":"README.rst","changelog":"HISTORY.rst","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":"giampaolo","patreon":null,"open_collective":null,"ko_fi":null,"community_bridge":null,"custom":"https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick\u0026hosted_button_id=ZSSF7G42VA2XE"}},"created_at":"2014-05-28T15:34:58.000Z","updated_at":"2025-11-12T07:53:21.000Z","dependencies_parsed_at":"2025-04-25T22:34:51.025Z","dependency_job_id":"c6131ab3-ae90-44af-bfe7-e566cc507f34","html_url":"https://github.com/giampaolo/pyftpdlib","commit_stats":{"total_commits":1367,"total_committers":36,"mean_commits":37.97222222222222,"dds":0.06291148500365762,"last_synced_commit":"a73a7eb7792596468969344a4d9c291ef4d94f07"},"previous_names":[],"tags_count":30,"template":false,"template_full_name":null,"purl":"pkg:github/giampaolo/pyftpdlib","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/giampaolo%2Fpyftpdlib","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/giampaolo%2Fpyftpdlib/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/giampaolo%2Fpyftpdlib/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/giampaolo%2Fpyftpdlib/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/giampaolo","download_url":"https://codeload.github.com/giampaolo/pyftpdlib/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/giampaolo%2Fpyftpdlib/sbom","scorecard":{"id":426047,"data":{"date":"2025-08-11","repo":{"name":"github.com/giampaolo/pyftpdlib","commit":"abb550318e6b725a2516ad3dd37b6a4a12bc8aec"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.5,"checks":[{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/tests.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Code-Review","score":1,"reason":"Found 3/29 approved changesets -- score normalized to 1","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":0,"reason":"1 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/tests.yml:22: update your workflow using https://app.stepsecurity.io/secureworkflow/giampaolo/pyftpdlib/tests.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/tests.yml:25: update your workflow using https://app.stepsecurity.io/secureworkflow/giampaolo/pyftpdlib/tests.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/tests.yml:41: update your workflow using https://app.stepsecurity.io/secureworkflow/giampaolo/pyftpdlib/tests.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/tests.yml:42: update your workflow using https://app.stepsecurity.io/secureworkflow/giampaolo/pyftpdlib/tests.yml/master?enable=pin","Warn: pipCommand not pinned by hash: .github/workflows/tests.yml:45","Info:   0 out of   4 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   1 pipCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 10 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}}]},"last_synced_at":"2025-08-19T02:16:50.834Z","repository_id":648916,"created_at":"2025-08-19T02:16:50.834Z","updated_at":"2025-08-19T02:16:50.834Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":284115869,"owners_count":26949957,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-11-12T02:00:06.336Z","response_time":59,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["asynchronous","ftp","ftp-server","ftps","python"],"created_at":"2024-07-31T22:02:07.889Z","updated_at":"2025-11-12T21:36:51.795Z","avatar_url":"https://github.com/giampaolo.png","language":"Python","readme":"|  |downloads| |stars| |forks| |contributors|\n|  |version| |packages| |license|\n|  |github-actions| |doc| |twitter|\n\n.. |downloads| image:: https://img.shields.io/pypi/dm/pyftpdlib.svg\n    :target: https://pepy.tech/project/pyftpdlib\n    :alt: Downloads\n\n.. |stars| image:: https://img.shields.io/github/stars/giampaolo/pyftpdlib.svg\n    :target: https://github.com/giampaolo/pyftpdlib/stargazers\n    :alt: Github stars\n\n.. |forks| image:: https://img.shields.io/github/forks/giampaolo/pyftpdlib.svg\n    :target: https://github.com/giampaolo/pyftpdlib/network/members\n    :alt: Github forks\n\n.. |contributors| image:: https://img.shields.io/github/contributors/giampaolo/pyftpdlib.svg\n    :target: https://github.com/giampaolo/pyftpdlib/graphs/contributors\n    :alt: Contributors\n\n.. |github-actions| image:: https://img.shields.io/github/actions/workflow/status/giampaolo/pyftpdlib/.github/workflows/tests.yml\n    :target: https://github.com/giampaolo/pyftpdlib/actions\n    :alt: GH actions\n\n.. |doc| image:: https://readthedocs.org/projects/pyftpdlib/badge/?version=latest\n    :target: https://pyftpdlib.readthedocs.io/en/latest/\n    :alt: Documentation Status\n\n.. |version| image:: https://img.shields.io/pypi/v/pyftpdlib.svg?label=pypi\n    :target: https://pypi.org/project/pyftpdlib\n    :alt: Latest version\n\n.. |py-versions| image:: https://img.shields.io/pypi/pyversions/psutil.svg\n    :alt: Supported Python versions\n\n.. |packages| image:: https://repology.org/badge/tiny-repos/python:pyftpdlib.svg\n    :target: https://repology.org/metapackage/python:pyftpdlib/versions\n    :alt: Binary packages\n\n.. |license| image:: https://img.shields.io/pypi/l/pyftpdlib.svg\n    :target: https://github.com/giampaolo/pyftpdlib/blob/master/LICENSE\n    :alt: License\n\n.. |twitter| image:: https://img.shields.io/twitter/follow/grodola.svg?label=follow\u0026style=flat\u0026logo=twitter\u0026logoColor=4FADFF\n    :target: https://twitter.com/grodola\n    :alt: Twitter Follow\n\nQuick links\n===========\n\n- `Home`_\n- `Documentation`_\n- `Download`_\n- `Mailing list`_\n- `What's new`_\n\nAbout\n=====\n\nPython FTP server library provides a high-level portable interface to easily\nwrite very efficient, scalable and asynchronous FTP servers with Python. It is\nthe most complete `RFC-959`_ FTP server implementation available for the\n`Python`_ programming language.\n\nFeatures\n========\n\n- Extremely **lightweight**, **fast** and **scalable** (see\n  `why \u003chttps://github.com/giampaolo/pyftpdlib/issues/203\u003e`__ and\n  `benchmarks`_).\n- Uses **sendfile(2)** (see `pysendfile \u003chttps://github.com/giampaolo/pysendfile\u003e`__)\n  system call for uploads (Linux only).\n- Uses ``epoll()`` / ``kqueue()`` / ``select()`` to handle concurrency\n  asynchronously.\n- ...But can optionally skip to a `multiple thread / process`_ model (as in:\n  you'll be free to block or use slow filesystems).\n- Portable: entirely written in pure Python.\n- Supports **FTPS** (`RFC-4217`_), **IPv6** (`RFC-2428`_), **Unicode** file\n  names (`RFC-2640`_), **MLSD/MLST** commands (`RFC-3659`_).\n- Support for virtual users and virtual filesystem.\n- Flexible system of \"authorizers\" able to manage both \"virtual\" and\n  \"real\" users on on both\n  `UNIX \u003chttps://pyftpdlib.readthedocs.io/en/latest/tutorial.html#unix-ftp-server\u003e`__\n  and\n  `Windows \u003chttps://pyftpdlib.readthedocs.io/en/latest/tutorial.html#windows-ftp-server\u003e`__.\n\nPerformances\n============\n\nDespite being written in an interpreted language, pyftpdlib has transfer rates\ncomparable or superior to common UNIX FTP servers written in C. It usually\ntends to scale better (see `benchmarks`_) because whereas vsftpd and proftpd\nuse multiple processes to achieve concurrency, pyftpdlib only uses one (see\n`the C10K problem`_).\n\npyftpdlib vs. proftpd 1.3.4\n---------------------------\n\n+-----------------------------------------+----------------+----------------+-------------+\n| **benchmark type**                      | **pyftpdlib**  | **proftpd**    | **speedup** |\n+-----------------------------------------+----------------+----------------+-------------+\n| STOR (client -\u003e server)                 |  585.90 MB/sec | 600.49 MB/sec  | -0.02x      |\n+-----------------------------------------+----------------+----------------+-------------+\n| RETR (server -\u003e client)                 | 1652.72 MB/sec | 1524.05 MB/sec | **+0.08**   |\n+-----------------------------------------+----------------+----------------+-------------+\n| 300 concurrent clients (connect, login) |    0.19 secs   | 9.98 secs      | **+51x**    |\n+-----------------------------------------+----------------+----------------+-------------+\n| STOR (1 file with 300 idle clients)     |  585.59 MB/sec | 518.55 MB/sec  | **+0.1x**   |\n+-----------------------------------------+----------------+----------------+-------------+\n| RETR (1 file with 300 idle clients)     | 1497.58 MB/sec | 1478.19 MB/sec | 0x          |\n+-----------------------------------------+----------------+----------------+-------------+\n| 300 concurrent clients (RETR 10M file)  |    3.41 secs   | 3.60 secs      | **+0.05x**  |\n+-----------------------------------------+----------------+----------------+-------------+\n| 300 concurrent clients (STOR 10M file)  |    8.60 secs   | 11.56 secs     | **+0.3x**   |\n+-----------------------------------------+----------------+----------------+-------------+\n| 300 concurrent clients (QUIT)           |    0.03 secs   | 0.39 secs      | **+12x**    |\n+-----------------------------------------+----------------+----------------+-------------+\n\npyftpdlib vs. vsftpd 2.3.5\n--------------------------\n\n+-----------------------------------------+----------------+----------------+-------------+\n| **benchmark type**                      | **pyftpdlib**  | **vsftpd**     | **speedup** |\n+-----------------------------------------+----------------+----------------+-------------+\n| STOR (client -\u003e server)                 |  585.90 MB/sec | 611.73 MB/sec  | -0.04x      |\n+-----------------------------------------+----------------+----------------+-------------+\n| RETR (server -\u003e client)                 | 1652.72 MB/sec | 1512.92 MB/sec | **+0.09**   |\n+-----------------------------------------+----------------+----------------+-------------+\n| 300 concurrent clients (connect, login) |    0.19 secs   | 20.39 secs     | **+106x**   |\n+-----------------------------------------+----------------+----------------+-------------+\n| STOR (1 file with 300 idle clients)     |  585.59 MB/sec | 610.23 MB/sec  | -0.04x      |\n+-----------------------------------------+----------------+----------------+-------------+\n| RETR (1 file with 300 idle clients)     | 1497.58 MB/sec | 1493.01 MB/sec | 0x          |\n+-----------------------------------------+----------------+----------------+-------------+\n| 300 concurrent clients (RETR 10M file)  |    3.41 secs   | 3.67 secs      | **+0.07x**  |\n+-----------------------------------------+----------------+----------------+-------------+\n| 300 concurrent clients (STOR 10M file)  |    8.60 secs   | 9.82 secs      | **+0.07x**  |\n+-----------------------------------------+----------------+----------------+-------------+\n| 300 concurrent clients (QUIT)           |    0.03 secs   | 0.01 secs      | +0.14x      |\n+-----------------------------------------+----------------+----------------+-------------+\n\nFor more benchmarks see `here \u003chttps://pyftpdlib.readthedocs.io/en/latest/benchmarks.html\u003e`__.\n\nCommand line usage\n==================\n\nStart an anonymous FTP server on port 2121:\n\n.. code-block:: sh\n\n    $ python3 -m pyftpdlib\n    [I 2024-06-23 13:49:35] \u003e\u003e\u003e starting FTP server on 0.0.0.0:2121, pid=763634 \u003c\u003c\u003c\n\nSame but with write permissions (useful to setup a quick and dirty file sharing server):\n\n.. code-block:: sh\n\n    $ python3 -m pyftpdlib --write\n    [I 2024-06-23 13:49:35] \u003e\u003e\u003e starting FTP server on 0.0.0.0:2121, pid=763641 \u003c\u003c\u003c\n\nAlso see `CLI doc \u003chttps://pyftpdlib.readthedocs.io/en/latest/cli.html\u003e`__\nfor more command line examples.\n\nAPI usage\n=========\n\n.. code-block:: python\n\n    \u003e\u003e\u003e from pyftpdlib.authorizers import DummyAuthorizer\n    \u003e\u003e\u003e from pyftpdlib.handlers import FTPHandler\n    \u003e\u003e\u003e from pyftpdlib.servers import FTPServer\n    \u003e\u003e\u003e\n    \u003e\u003e\u003e authorizer = DummyAuthorizer()\n    \u003e\u003e\u003e authorizer.add_user(\"user\", \"12345\", \"/home/giampaolo\", perm=\"elradfmwMT\")\n    \u003e\u003e\u003e authorizer.add_anonymous(\"/home/nobody\")\n    \u003e\u003e\u003e\n    \u003e\u003e\u003e handler = FTPHandler\n    \u003e\u003e\u003e handler.authorizer = authorizer\n    \u003e\u003e\u003e\n    \u003e\u003e\u003e server = FTPServer((\"127.0.0.1\", 21), handler)\n    \u003e\u003e\u003e server.serve_forever()\n    [I 13-02-19 10:55:42] \u003e\u003e\u003e starting FTP server on 127.0.0.1:21 \u003c\u003c\u003c\n    [I 13-02-19 10:55:42] poller: \u003cclass 'pyftpdlib.ioloop.Epoll'\u003e\n    [I 13-02-19 10:55:42] masquerade (NAT) address: None\n    [I 13-02-19 10:55:42] passive ports: None\n    [I 13-02-19 10:55:42] use sendfile(2): True\n    [I 13-02-19 10:55:45] 127.0.0.1:34178-[] FTP session opened (connect)\n    [I 13-02-19 10:55:48] 127.0.0.1:34178-[user] USER 'user' logged in.\n    [I 13-02-19 10:56:27] 127.0.0.1:34179-[user] RETR /home/giampaolo/.vimrc completed=1 bytes=1700 seconds=0.001\n    [I 13-02-19 10:56:39] 127.0.0.1:34179-[user] FTP session closed (disconnect).\n\nFor other code samples read the `tutorial \u003chttps://pyftpdlib.readthedocs.io/en/latest/tutorial.html\u003e`__\n\nDonate\n======\n\nA lot of time and effort went into making pyftpdlib as it is right now.\nIf you feel pyftpdlib is useful to you or your business and want to support its\nfuture development please consider `donating`_ me some money.\n\n.. _`benchmarks`: https://pyftpdlib.readthedocs.io/en/latest/benchmarks.html\n.. _`Documentation`: https://pyftpdlib.readthedocs.io\n.. _`donating`: https://gmpy.dev/donate\n.. _`Download`: https://pypi.org/project/pyftpdlib/\n.. _`Home`: https://github.com/giampaolo/pyftpdlib\n.. _`Mailing list`: https://groups.google.com/group/pyftpdlib/topics\n.. _`multiple thread / process`: https://pyftpdlib.readthedocs.io/en/latest/tutorial.html#changing-the-concurrency-model\n.. _`Python`: https://www.python.org/\n.. _`RFC-2428`: https://datatracker.ietf.org/doc/html/rfc2428\n.. _`RFC-2640`: https://datatracker.ietf.org/doc/html/rfc2640\n.. _`RFC-3659`: https://datatracker.ietf.org/doc/html/rfc3659\n.. _`RFC-4217`: https://datatracker.ietf.org/doc/html/rfc4217\n.. _`RFC-959`: https://datatracker.ietf.org/doc/html/rfc959.html\n.. _`the C10K problem`: http://www.kegel.com/c10k.html\n.. _`What's new`: https://github.com/giampaolo/pyftpdlib/blob/master/HISTORY.rst\n","funding_links":["https://github.com/sponsors/giampaolo","https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick\u0026hosted_button_id=ZSSF7G42VA2XE"],"categories":["资源列表","Python","Software"],"sub_categories":["命令行工具","File Management"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgiampaolo%2Fpyftpdlib","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgiampaolo%2Fpyftpdlib","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgiampaolo%2Fpyftpdlib/lists"}