用Python创建一个FTP客户端 [英] Creating an FTP client with Python

查看:106
本文介绍了用Python创建一个FTP客户端的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

自从我开始使用互联网以来,我一直都在考虑创建自己的ftp客户端。现在我正在学习Python,我正在考虑创建一个作为练习/个人项目。



我想知道,


  • 你们建议哪些图书馆?请问 ftplib 就够了吗?或者你会建议另一个库(最好有一个文档好)?

  • 我正在考虑使用wxPython。这是个好主意吗?我应该先学习吗?

  • 我来自Web开发背景。你们会给我什么提示/建议?



我会很感激任何指导/帮助。提前致谢! :)

解决方案

听起来你想制作一个具有GUI的程序。我可以推荐你的应用程序的那一部分使用 PyQt 吗? ftplib 应该适用于您的FTP支持,并且您可以查找文档在这里



另外,对于FTP支持,您可以使用 QtNetwork 中的 QFtp 模块来自 PyQt 框架。以下是PyQt附带的示例FTP客户端。



pre $ #!/ usr / bin / env python

网络的PyQt4端口/来自Qt v4.x的ftp示例

#这只是Python v2所必需的,但对于Python v3是无害的。
导入sip
从PyQt4导入sip.setapi('QString',2)

导入QtCore,QtGui,QtNetwork

导入ftp_rc


class FtpWindow(QtGui.QDialog):
def __init __(self,parent = None):
super(FtpWindow,self).__ init __(parent)

self.isDirectory = {}
self.currentPath =''
self.ftp = None
self.outFile = None

ftpServerLabel = QtGui.QLabel (Ftp& server:)
self.ftpServerLineEdit = QtGui.QLineEdit('ftp.trolltech.com')
ftpServerLabel.setBuddy(self.ftpServerLineEdit)

self .statusLabel = QtGui.QLabel(请输入FTP服务器的名称。)

self.fileList = QtGui.QTreeWidget()
self.fileList.setEnabled(False)
self.fileList.setRootIsDecorated(False)
self.fileList.setHeaderLabels((Name,Size,Owner,Group,Time))
self.fileList。标题()。setStr etchLastSection(False)

self.connectButton = QtGui.QPushButton(Connect)
self.connectButton.setDefault(True)
$ b $ self.cdToParentButton = QtGui。 QPushButton()
self.cdToParentButton.setIcon(QtGui.QIcon(':/ images / cdtoparent.png'))
self.cdToParentButton.setEnabled(False)

self。 downloadButton = QtGui.QPushButton(Download)
self.downloadButton.setEnabled(False)

self.quitButton = QtGui.QPushButton(Quit)

buttonBox = QtGui.QDialogBu​​ttonBox()
buttonBox.addButton(self.downloadButton,
QtGui.QDialogBu​​ttonBox.ActionRole)
buttonBox.addButton(self.quitButton,QtGui.QDialogBu​​ttonBox.RejectRole)

self.progressDialog = QtGui.QProgressDialog(self)

self.fileList.itemActivated.connect(self.processItem)
self.fileList.currentItemChanged.connect(self.enableDownloadButto n)
self.progressDialog.canceled.connect(self.cancelDownload)
self.connectButton.clicked.connect(self.connectOrDisconnect)
self.cdToParentButton.clicked.connect(self.cdToParent)
self.downloadButton.clicked.connect(self.downloadFile)
self.quitButton.clicked.connect(self.close)

topLayout = QtGui.QHBoxLayout()
topLayout.addWidget(ftpServerLabel)
topLayout.addWidget(self.ftpServerLineEdit)
topLayout.addWidget(self.cdToParentButton)
topLayout.addWidget(self.connectButton)

mainLayout = QtGui.QVBoxLayout()
mainLayout.addLayout(topLayout)
mainLayout.addWidget(self.fileList)
mainLayout.addWidget(self.statusLabel)
mainLayout.addWidget( buttonBox)
self.setLayout(mainLayout)

self.setWindowTitle(FTP)

def sizeHint(self):
return QtCore.QS ize(500,300)

def connectOrDisconnect(self):
如果self.ftp:
self.ftp.abort()
self.ftp.deleteLater )
self.ftp = None

self.fileList.setEnabled(False)
self.cdToParentButton.setEnabled(False)
self.downloadButton.setEnabled(False)
self.connectButton.setEnabled(True)
self.connectButton.setText(Connect)
self.setCursor(QtCore.Qt.ArrowCursor)

return

self.setCursor(QtCore.Qt.WaitCursor)

self.ftp = QtNetwork.QFtp(self)
self.ftp.commandFinished.connect(self.ftpCommandFinished )
self.ftp.listInfo.connect(self.addToList)
self.ftp.dataTransferProgress.connect(self.updateDataTransferProgress)

self.fileList.clear()
self.currentPath =''
self.isDirectory.clear()

url = QtCore.QUrl(self.ftpServerLineEdit.text())
如果不是url.isValid()或url.scheme()。lower()!='ftp':
self.ftp.connectToHost (self.ftpServerLineEdit.text(),21)
self.ftp.login()
else:
self.ftp.connectToHost(url.host(),url.port(21) )

user_name = url.userName()
if user_name:
try:
#Python v3。
user_name = bytes(user_name,encoding ='latin1')
除了:
#Python v2。
传递

self.ftp.login(QtCore.QUrl.fromPercentEncoding(user_name),url.password())
else:
self.ftp.login( )

如果url.path():
self.ftp.cd(url.path())

self.fileList.setEnabled(True)
self.connectButton.setEnabled(False)
self.connectButton.setText(Disconnect)
self.statusLabel.setText(正在连接到FTP服务器%s ...%self.ftpServerLineEdit。 text())
$ b $ def downloadFile(self):
fileName = self.fileList.currentItem()。text(0)
$ b $如果QtCore.QFile.exists (fileName):
QtGui.QMessageBox.information(self,FTP,
在当前的
目录中已经存在一个名为%s的文件。%fileName)
返回

self.outFile = QtCore.QFile(文件名)
如果不是self.outFile.open(QtCo re.QIODevice.WriteOnly):
QtGui.QMessageBox.information(self,FTP,
无法保存文件%s:%s。%(fileName,self.outFile.errorString( )))
self.outFile = None
return

self.ftp.get(self.fileList.currentItem().text(0),self.outFile)

self.progressDialog.setLabelText(正在下载%s ...%fileName)
self.downloadButton.setEnabled(False)
self.progressDialog.exec_()

def cancelDownload(self):
self.ftp.abort()

def ftpCommandFinished(self,_,error):
self.setCursor(QtCore.Qt .ArrowCursor)

if self.ftp.currentCommand()== QtNetwork.QFtp.ConnectToHost:
if error:
QtGui.QMessageBox.information(self,FTP,
无法连接到位于%s的FTP服务器。请
检查主机名是否正确。%self.ftpServerLineEdit.text())
self.connectOrDisconnect()
返回

self.statusLabel .setText(登录到%s。%self.ftpServerLineEdit.text())
self.fileList.setFocus()
self.downloadButton.setDefault(True)
self.connectButton。 setEnabled(True)
返回

if self.ftp.currentCommand()== QtNetwork.QFtp.Login:
self.ftp.list()

if self.ftp.currentCommand()== QtNetwork.QFtp.Get:
if error:
self.statusLabel.setText(已取消%s的下载。%self.outFile.fileName( ))
self.outFile.close()
self.outFile.remove()
else:
self.statusLabel.setText(已下载%s到当前目录。% self.outFile.fileName())
self.outFile.close()

self.outFile = None
self.enableDownloadButton()
self.progressDialog.hide()
elif self.ftp.currentCommand ()== QtNetwork.QFtp.List:
如果不是self.isDirectory:
self.fileList.addTopLevelItem(QtGui.QTreeWidgetItem([< empty>)))
self。 fileList.setEnabled(False)
$ b $ def addToList(self,urlInfo):
item = QtGui.QTreeWidgetItem()
item.setText(0,urlInfo.name())
item.setText(1,str(urlInfo.size()))
item.setText(2,urlInfo.owner())
item.setText(3,urlInfo.group())
item.setText(4,urlInfo.lastModified()。toString('MMM dd yyyy'))

if urlInfo.isDir():
icon = QtGui.QIcon ':/images/dir.png')
else:
icon = QtGui.QIcon(':/ images / file.png')
item.setIcon(0,icon)

如果不是self.fileList.currentItem():
self.fileList。 setCurrentItem(self.fileList.topLevelItem(0))
self.fileList.setEnabled(True)

def processItem(self,item):
name = item.text(0 )
self.isDirectory.get(name):
self.fileList.clear()
self.isDirectory.clear()
self.currentPath + ='/'+名称
self.ftp.cd(名称)
self.ftp.list()
self.cdToParentButton.setEnabled(True)
self.setCursor(QtCore.Qt.WaitCursor)
$ b $ def cdToParent(self):
self.setCursor(QtCore.Qt.WaitCursor)
self.fileList.clear()
self.isDirectory.clear()

dirs = self.currentPath.split('/')
if len(dirs)> 1:
self.currentPath =''
self.cdToParentButton.setEnabled(False)
self.ftp.cd('/')
else:
self。 currentPath ='/'.join(dirs[:-1])$ ​​b $ b self.ftp.cd(self.currentPath)

self.ftp.list()

def updateDataTransferProgress(self,readBytes,totalBytes):
self.progressDialog.setMaximum(totalBytes)
self.progressDialog.setValue(readBytes)
$ b $ def enableDownloadButton(self):
current = self.fileList.currentItem()
if current:
currentFile = current.text(0)
self.downloadButton.setEnabled(not self.isDirectory.get(currentFile ))
else:
self.downloadButton.setEnabled(False)


if __name__ =='__main__':

import sys

app = QtGui.QApplication(sys.argv)
ftpWin = FtpWindow()
ftpWin.show()
sys.exit(ftpWin.exec_())


I've always thought about creating my own ftp client ever since I've started using the Internet. And now that I'm studying Python, I'm thinking about creating one as an exercises/personal project.

I'm wondering,

  • What libraries do you guys suggest? Will ftplib suffice? Or would you suggest another library(preferably one that has good docs)?
  • I'm thinking about using wxPython. Is it a good idea? Should I learn it first?
  • I'm coming from a Web Development background. What tips/suggestions would you guys give to me?

I'd appreciate any guidance/help. Thanks in advance! :)

解决方案

It sounds like you want to make a program that has a GUI. May I recommend using PyQt for that part of your application? ftplib should be fine for your FTP support, and you can find documentation right here.

Alternatively for FTP support, you can use the QFtp class from the QtNetwork module from PyQt framework. The following is an example FTP client that comes with PyQt. The images come with it.

#!/usr/bin/env python

"""PyQt4 port of the network/ftp example from Qt v4.x"""

# This is only needed for Python v2 but is harmless for Python v3.
import sip
sip.setapi('QString', 2)

from PyQt4 import QtCore, QtGui, QtNetwork

import ftp_rc


class FtpWindow(QtGui.QDialog):
    def __init__(self, parent=None):
        super(FtpWindow, self).__init__(parent)

        self.isDirectory = {}
        self.currentPath = ''
        self.ftp = None
        self.outFile = None

        ftpServerLabel = QtGui.QLabel("Ftp &server:")
        self.ftpServerLineEdit = QtGui.QLineEdit('ftp.trolltech.com')
        ftpServerLabel.setBuddy(self.ftpServerLineEdit)

        self.statusLabel = QtGui.QLabel("Please enter the name of an FTP server.")

        self.fileList = QtGui.QTreeWidget()
        self.fileList.setEnabled(False)
        self.fileList.setRootIsDecorated(False)
        self.fileList.setHeaderLabels(("Name", "Size", "Owner", "Group", "Time"))
        self.fileList.header().setStretchLastSection(False)

        self.connectButton = QtGui.QPushButton("Connect")
        self.connectButton.setDefault(True)

        self.cdToParentButton = QtGui.QPushButton()
        self.cdToParentButton.setIcon(QtGui.QIcon(':/images/cdtoparent.png'))
        self.cdToParentButton.setEnabled(False)

        self.downloadButton = QtGui.QPushButton("Download")
        self.downloadButton.setEnabled(False)

        self.quitButton = QtGui.QPushButton("Quit")

        buttonBox = QtGui.QDialogButtonBox()
        buttonBox.addButton(self.downloadButton,
                QtGui.QDialogButtonBox.ActionRole)
        buttonBox.addButton(self.quitButton, QtGui.QDialogButtonBox.RejectRole)

        self.progressDialog = QtGui.QProgressDialog(self)

        self.fileList.itemActivated.connect(self.processItem)
        self.fileList.currentItemChanged.connect(self.enableDownloadButton)
        self.progressDialog.canceled.connect(self.cancelDownload)
        self.connectButton.clicked.connect(self.connectOrDisconnect)
        self.cdToParentButton.clicked.connect(self.cdToParent)
        self.downloadButton.clicked.connect(self.downloadFile)
        self.quitButton.clicked.connect(self.close)

        topLayout = QtGui.QHBoxLayout()
        topLayout.addWidget(ftpServerLabel)
        topLayout.addWidget(self.ftpServerLineEdit)
        topLayout.addWidget(self.cdToParentButton)
        topLayout.addWidget(self.connectButton)

        mainLayout = QtGui.QVBoxLayout()
        mainLayout.addLayout(topLayout)
        mainLayout.addWidget(self.fileList)
        mainLayout.addWidget(self.statusLabel)
        mainLayout.addWidget(buttonBox)
        self.setLayout(mainLayout)

        self.setWindowTitle("FTP")

    def sizeHint(self):
        return QtCore.QSize(500, 300)

    def connectOrDisconnect(self):
        if self.ftp:
            self.ftp.abort()
            self.ftp.deleteLater()
            self.ftp = None

            self.fileList.setEnabled(False)
            self.cdToParentButton.setEnabled(False)
            self.downloadButton.setEnabled(False)
            self.connectButton.setEnabled(True)
            self.connectButton.setText("Connect")
            self.setCursor(QtCore.Qt.ArrowCursor)

            return

        self.setCursor(QtCore.Qt.WaitCursor)

        self.ftp = QtNetwork.QFtp(self)
        self.ftp.commandFinished.connect(self.ftpCommandFinished)
        self.ftp.listInfo.connect(self.addToList)
        self.ftp.dataTransferProgress.connect(self.updateDataTransferProgress)

        self.fileList.clear()
        self.currentPath = ''
        self.isDirectory.clear()

        url = QtCore.QUrl(self.ftpServerLineEdit.text())
        if not url.isValid() or url.scheme().lower() != 'ftp':
            self.ftp.connectToHost(self.ftpServerLineEdit.text(), 21)
            self.ftp.login()
        else:
            self.ftp.connectToHost(url.host(), url.port(21))

            user_name = url.userName()
            if user_name:
                try:
                    # Python v3.
                    user_name = bytes(user_name, encoding='latin1')
                except:
                    # Python v2.
                    pass

                self.ftp.login(QtCore.QUrl.fromPercentEncoding(user_name), url.password())
            else:
                self.ftp.login()

            if url.path():
                self.ftp.cd(url.path())

        self.fileList.setEnabled(True)
        self.connectButton.setEnabled(False)
        self.connectButton.setText("Disconnect")
        self.statusLabel.setText("Connecting to FTP server %s..." % self.ftpServerLineEdit.text())

    def downloadFile(self):
        fileName = self.fileList.currentItem().text(0)

        if QtCore.QFile.exists(fileName):
            QtGui.QMessageBox.information(self, "FTP",
                    "There already exists a file called %s in the current "
                    "directory." % fileName)
            return

        self.outFile = QtCore.QFile(fileName)
        if not self.outFile.open(QtCore.QIODevice.WriteOnly):
            QtGui.QMessageBox.information(self, "FTP",
                    "Unable to save the file %s: %s." % (fileName, self.outFile.errorString()))
            self.outFile = None
            return

        self.ftp.get(self.fileList.currentItem().text(0), self.outFile)

        self.progressDialog.setLabelText("Downloading %s..." % fileName)
        self.downloadButton.setEnabled(False)
        self.progressDialog.exec_()

    def cancelDownload(self):
        self.ftp.abort()

    def ftpCommandFinished(self, _, error):
        self.setCursor(QtCore.Qt.ArrowCursor)

        if self.ftp.currentCommand() == QtNetwork.QFtp.ConnectToHost:
            if error:
                QtGui.QMessageBox.information(self, "FTP",
                        "Unable to connect to the FTP server at %s. Please "
                        "check that the host name is correct." % self.ftpServerLineEdit.text())
                self.connectOrDisconnect()
                return

            self.statusLabel.setText("Logged onto %s." % self.ftpServerLineEdit.text())
            self.fileList.setFocus()
            self.downloadButton.setDefault(True)
            self.connectButton.setEnabled(True)
            return

        if self.ftp.currentCommand() == QtNetwork.QFtp.Login:
            self.ftp.list()

        if self.ftp.currentCommand() == QtNetwork.QFtp.Get:
            if error:
                self.statusLabel.setText("Canceled download of %s." % self.outFile.fileName())
                self.outFile.close()
                self.outFile.remove()
            else:
                self.statusLabel.setText("Downloaded %s to current directory." % self.outFile.fileName())
                self.outFile.close()

            self.outFile = None
            self.enableDownloadButton()
            self.progressDialog.hide()
        elif self.ftp.currentCommand() == QtNetwork.QFtp.List:
            if not self.isDirectory:
                self.fileList.addTopLevelItem(QtGui.QTreeWidgetItem(["<empty>"]))
                self.fileList.setEnabled(False)

    def addToList(self, urlInfo):
        item = QtGui.QTreeWidgetItem()
        item.setText(0, urlInfo.name())
        item.setText(1, str(urlInfo.size()))
        item.setText(2, urlInfo.owner())
        item.setText(3, urlInfo.group())
        item.setText(4, urlInfo.lastModified().toString('MMM dd yyyy'))

        if urlInfo.isDir():
            icon = QtGui.QIcon(':/images/dir.png')
        else:
            icon = QtGui.QIcon(':/images/file.png')
        item.setIcon(0, icon)

        self.isDirectory[urlInfo.name()] = urlInfo.isDir()
        self.fileList.addTopLevelItem(item)
        if not self.fileList.currentItem():
            self.fileList.setCurrentItem(self.fileList.topLevelItem(0))
            self.fileList.setEnabled(True)

    def processItem(self, item):
        name = item.text(0)
        if self.isDirectory.get(name):
            self.fileList.clear()
            self.isDirectory.clear()
            self.currentPath += '/' + name
            self.ftp.cd(name)
            self.ftp.list()
            self.cdToParentButton.setEnabled(True)
            self.setCursor(QtCore.Qt.WaitCursor)

    def cdToParent(self):
        self.setCursor(QtCore.Qt.WaitCursor)
        self.fileList.clear()
        self.isDirectory.clear()

        dirs = self.currentPath.split('/')
        if len(dirs) > 1:
            self.currentPath = ''
            self.cdToParentButton.setEnabled(False)
            self.ftp.cd('/')
        else:
            self.currentPath = '/'.join(dirs[:-1])
            self.ftp.cd(self.currentPath)

        self.ftp.list()

    def updateDataTransferProgress(self, readBytes, totalBytes):
        self.progressDialog.setMaximum(totalBytes)
        self.progressDialog.setValue(readBytes)

    def enableDownloadButton(self):
        current = self.fileList.currentItem()
        if current:
            currentFile = current.text(0)
            self.downloadButton.setEnabled(not self.isDirectory.get(currentFile))
        else:
            self.downloadButton.setEnabled(False)


if __name__ == '__main__':

    import sys

    app = QtGui.QApplication(sys.argv)
    ftpWin = FtpWindow()
    ftpWin.show()
    sys.exit(ftpWin.exec_())

这篇关于用Python创建一个FTP客户端的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆