lib

How to Create a Python Library



In this tutorial, our goal is to create a Python Library which is a FTP class that is well written, useful, and expandable.

Outlining our Objective

It’s always important to first outline exactly what functionality your class should include. In our case:

  • connecting to a server
  • create a folder on the server
  • upload a file
  • change directory
  • retrieving the directory listing
  • download a file

When Would I Use an FTP Class?

There are several instances when one might use this sort of class. A couple of scenarios could be:

  • Automate uploading of images, such as a gallery, to a client’s website.
  • Perform off-site backups by transferring a database backup file from your server to another. (Note: This isn’t recommended for sensitive information as FTP is not a very secure protocol.)

Note: It’s easy to run into issues with FTP due to different server configurations. This code has been tested on a number of FTP servers successfully.

What is FTP?

FTP: ”A standard network protocol used to copy a file from one host to another.”

FTP, or File Transfer Protocol, is, as defined by Wikipedia: “A standard network protocol used to copy a file from one host to another over a TCP/IP-based network, such as the Internet.”

Essentially, it allows you to copy a file(s) from one computer to another.

Step 1 - Preparation

We’ll start off as easy as possible. Create a directory called PyTransmit In your new project’s root, create one files: ftp.py inside the directory.

In the next step, we’re going to create the skeleton for our class. Once this is in place, you’ll be able to follow along and try each step.

Step 2 - Setting up the Class

The strength of Object-Oriented Programming (OOP) is to give complex code an easy to use interface. By creating a class — think of a class as a pattern — you can encapsulate the data, which is simply jargon for a term that refers to hiding the data. We can then reuse this class over and over without the need to rewrite any of the code. Instead, you only need to call the appropriate methods (the term “method” is the same as function).

Let’s begin creating our ftp class. Open your ftp.py file, and add the following code. This is a basic class skeleton structure, which I’ve named ‘FTPClient‘.

The __init__ function, known as a constructor, is a special class method that is automatically called by the class when you create a new object, or instance of the class. This is typically a good place to add some initialization; but for today’s purpose, we don’t need it. Nonetheless, we’ll keep it here for future use.

Step 3 - Class Variables

Next, we’ll set set some class variables, or properties.

Step 4 - Simple Message Logging

In nearly every method, we’re going to call a method, named ‘logMessage. This is a very basic message handler, that will allow us to capture any messages created by our class so that we can provide the user with feedback.

Note that we don’t return the actual messages from within our methods. Instead, we return true or false, based upon whether or not a particular operation was successful. This has its advantages, but also doesn’t detail to the user what’s happening.

Add the following two methods, so we can determine what’s successful.

This method accepts a variable, message. The contents of this variable are then saved into our class array, thanks to the line: self.message_array[] = message.

Because messag_array is a class variable, we can access it, via the self. notation.

To retrieve the message, we call get_message.

Note: There are plenty examples around the web of full blown message handlers, or classes dedicated to them. We’re working on a simple implementation for the purpose of this tutorial.

Step 5 - Connecting

In this step, we’ll add the connect method. This will allow us to connect to an FTP server.

We pass in our connection information: the server (server), username (ftp_user), and password (ftp_password) to allow us to establish a connection.

The first line of code opens an FTP connection, with ftp.connect, to the specified server.

The code, ftp.login logs us in to the specified connection, passing in our username, and password.

We determine if the connection was successful. We then log the results by calling our simple message handler method, log_message(), and pass the string to log. Remember: we use self. to access log_message(), as it is a class variable.

Step 6 - Calling the Object

Now that our class is working, we can test it out! Open your config.py file, and add the following code.

You’ll need access to an FTP server to play along. If you wish to set your own server up, try Filezilla - it’s free, too.

You’ll notice I’ve added the FTP server details here. Ideally these would be stored within your config file. Change these to match the settings of your FTP server.

Ftp.py till now:

After defining our FTP server details, we include the class with from ftp import FTPClient. This means: make the class available from within this page. The next line creates an object of our FTP class, and stores it in the variable, ftp_objftp_obj will now be used to access any public methods within our class. This is done by using the . notation, just like the following line does by calling the ftp_obj.connect() method and passing it our server details.

Config.py

As you can see, once our class is in place, connecting to our FTP server is really quite easy!

Step 7 - Making our First Directory

Excellent, now it’s time to do something useful. The first method we’re going to create is the make_directory method. As expected, this method will create directories for us on the server. The only parameter we will pass is the directory path and folder name; we’ll call it directory. The magical line here is the mkd built-in function. It uses directory variable to create the folder.

Add the following code to your ftp.py file:

And, to call it from your config.py file, add:

The variable, directory is set to the name of the folder we want to create on the server. In this case: “/test”.

The next line calls the method that will create the folder.

If you receive a “Permission denied” error, make sure that you can write in the folder specified. You might need to create the folder within a directory, such as /httpdocs. 

Step 8 - Uploading a File

Continuing on, let’s upload a photo, called zoe.jpg. When uploading a file, we need to specify what type of file we’re uploading - binary or ascii? Basically, if you’re uploading a text file, we should use ascii; otherwise, it should be set to binary.

Certainly, you can create or upload any folder name you wish! Add this next snippet of code to your config.py file, and adjust accordingly.

By now, you should be coming to terms with just how easy this class is to use! We’re merely making single calls to perform our tasks — all thanks to object orientated programming!

Step 9 - Viewing the Files

Let’s now confirm that our file is in the test folder. We can do so by navigating to the ‘test‘ folder on our server, and then display the contents.

The change_directory method uses “cwd” to changes the current directory on the ftp server. Simply pass in the directory to change to. Simple and sweet.

get_directory_listing will display the contents of the directory you’re in by using the function “dir“. This function returns a list of files in a given directory. The current directory is set by default, so you don’t need to provide any parameters.

If you wish, you can override this by passing in the directory path you wish to view the contents of. The parameters variable defaults to ‘-la‘. This is a Linux command to display more information about the directory. Feel free to remove it or pass in an empty string.

The get_directory_listing method returns an array which contains our directory listing.

config.py

Step 10 - Downloading a File

As we push toward the conclusion of this tutorial, we next move on to downloading the file. The method starts with the same code as upload_file, in that it determines if the file we want to download is ascii or binary.

For this method, you simply pass in the filename (and possibly the path, depending on if you’re in the same folder as the file you wish to download) of the file to download, and the name you wish that file to have on your client machine.

In order to download a file, place this code:

We’re going to download the same file we uploaded by saving it with a different name on our client machine.

Note: Again, make sure that your permissions are set correctly!

Step 11 - Check for Existing Directory

Step 12 – Finishing Up

To complete our class, let’s add the class magic method, __del__. This method closes our connection when the reference to our object no longer exists – maybe the page was closed. In any event, this code is run and the connection is closed. It’s always a good practice to include this, though it’s not entirely necessary.

Completed Code:

What is PyPI ?

From the official website:

PyPI — the Python Package Index

The Python Package Index is a repository of software for the Python programming language.

Written something cool? Want others to be able to install it with easy_install or pip? Put your code on PyPI. It’s a big list of python packages that you absolutely must submit your package to for it to be easily one-line installable.

Instructions

The good news is that submitting to PyPI is simple in theory: just sign up and upload your code, all for free. The bad news is that in practice it’s a little bit more complicated than that. The other good news is that I’ve written this guide, and that if you’re stuck, you can always refer to the official documentation.

I’ve written this guide with the following assumptions:

  • The module/library/package that you’re submitting is called mypackage.
  • mypackage is hosted on github.

Create your accounts

On PyPI Live and also on PyPI Test. You must create an account in order to be able to upload your code. I recommend using the same email/password for both accounts, just to make your life easier when it comes time to push.

Create a .pypirc configuration file

This config file holds your information for authenticating with PyPI.

this is just to make your life easier, so that when it comes time to upload you don’t have to type/remember your username and password

Prepare your package

Every package on PyPI needs to have a file called setup.py at the root of the directory. If your’e using a markdown-formatted read me file you’ll also need a setup.cfg file. Also, you’ll want a LICENSE.txt file describing what can be done with your code. So if I’ve been working on a library called mypackage, my directory structure would look like this:

Here’s a breakdown of what goes in which file:

  • setup.py This is metadata about your library.

The download_url is a link to a hosted file with your repository’s code. Github will host this for you, but only if you create a git tag. In your repository, type: git tag 0.1 -m "Adds a tag so that we can put this on PyPI". Then, type git tag to show a list of tags — you should see 0.1 in the list. Type git push --tags origin master to update your code on Github with the latest tag information. Github creates tarballs for download at https://github.com/{username}/{module_name}/tarball/{tag}.

  • setup.cfg tells PyPI where your README file is.

This is necessary if you’re using a markdown readme file. At upload time, you may still get some errors about the lack of a readme — don’t worry about it.

  • LICENSE.txt whatever license you want your code to have. I tend to use the MIT license.

Register your package

In your directory, run the command python setup.py register -r PyPI-test

Upload your package

Upload to PyPI Test

In your directory, run the command python setup.py sdist upload -r PyPI-test. You should get no errors, and should also now be able to see your library in the test PyPI repository.

Upload to PyPI Live

Run

and you’re done.

Conclusion

Well that does it! I hope you now have a better understanding of how to use FTP with Python and upload a library to PyPi. You should now have the necessary skills to further expand this class to support other common tasks, such as renaming or deleting files and folders.

Be sure to let us know if you create any cool Python FTP clients!

1. PyTransmit Github Repo.
2. PyTransmit Documentation.


  • Sven

    First of all very nice and detailed explained. Especially I like the distutils part, showing how to distribute.
    Further I want to remark that your ftp client example, since you mentioned that library aspect that it should cover, could be improved in the point of exception handling. Meaning all sys.exit() calls should go away if is a library. For cli programm I could live with that. But the catch call exception handling is explicit mentioned as don’t in the python idioms.
    Also one more note about a library code: wouldn’t it be nice to have this piece of code unit tested? There u could easyliy mock the ftp var and validate certain method calls against the mock. This would take u just minimal effort more and u could promote that also in context of test driven development.
    I would recomment test code a la unittest anyway if a publication on pypi is the desired goal.

    But despite of this: well done.
    Thanks

  • http://laike9m.com/ laike9m

    Well done, I’ve always been curious about how to submit a package, thank you!

  • wappyzen

    I’m getting an error when I try to register the package with PyPI-test:

    ValueError: PyPI-test not found in .pypirc