Simpler times

Importing things

I’m creating the blog's code structure. First I’ve created a class and a repository for posts. They are in a subdirectory. I don’t know if this is the correct structure for a project, but I’ll start this way and refactor later if needed. The current structure is like this:


.
├── build.py
├── config.py
├── fr.sh
├── instance
├── Pipfile
├── README.md
├── run.py
└── simplertimes
    ├── __init__.py
    ├── posts
    │   ├── __init__.py
    │   ├── post.py
    │   ├── posts_repository.py
    ├── static
    │   └── uploads
    └── templates

'fr.sh' is the script I use to call Flask. `build.py` is the script to call Flask Frozen and build the site. 'instance' directory is created automatically (I don’t know its use yet) and 'simplertimes' is where the app is located.

The app bootstrap occurs in '/simplertimes/__init__.py'. For now, that’s the only file that contains code. From now on I have the functions to manage the routes and render templates:

    
        from flask import Flask, render_template

        def create_app(test_config=None):
            app = Flask(__name__, instance_relative_config=True)
            app.config.from_object('config')
        
            @app.route('/')
            def root():
                    return render_template('/index.html')
        
            return app
    
‘simplertimes’ directory is a python package. So, in fr.sh, I have this code:
    
        export FLASK_APP=simplertimes
        export FLASK_ENV=development
        flask run
    

It seems that flask imports the package. When you import a package the code on __init__.py is executed, so flask can get the app object and start serving it. The name of create_app function is a Flask’s convention. For example, if I rename it ‘banana’ nothing works.

Now, I want to use Post and PostRepository in create_app function. I’ve used one file for each class and placed them inside ‘posts’ directory. Doing that I have the following structure:

In Ruby I would have done something similar, creating post.rb and post_repository.rb in `posts` directory and then, in main code:

        
            require './postsrb/post'
            require './postsrb/posts_repository'
        
    

This would have led me to With that I could use both classes directly:

        
            p = Post.new()
            r = PostsRepository.new()
        
    

However, Python works differently. Instead of executing code and importing everything defined there into the main namespace, it creates a namespace for every module imported. So if I do:

        
            import posts.post
            import posts.posts_repository
        
    

I won't be able to use the classes this way:

        
            p = posts.post.Post()
            r = PostsRepository()
            NameError: name 'Post' is not defined
        
    

That is because each class is defined in its own namespace. When I import a module, I import the module namespace into this namespace: instead of having Post defined we have posts.post namespace defined and, inside it, the Post class. So I must refer to the namespace when I use the class:

p = posts.post.Post()

That is very verbose; and, if we change the code’s structure, we should change all occurrences in our code.

There is another way of importing the classes: instead of importing the module’s namespace, we can import something defined into that namespace directly into the current namespace:

        
            from posts.post import Post
            p = Post()
        
    

This is more similar to the Ruby’s version, but in this case, we are only importing one of the definitions of the module. If we want it to work like in Ruby we can import everything this way:

from posts.post import *

At first, I was frustrated with Python’s way, but now I realize it is more flexible than Ruby’s. There is another thing we can do to improve the import of the posts classes to import all at once with a single command:

        
            from posts import *
            p = Post()
            r = PostsRepository()
        
    

The trick is using '__init__.py' file of posts directory. Remember, 'posts' is a package and, when it is imported, __init__ is executed. If we import all submodules’ definitions in that file, then those definitions will be imported when we import the module. The contents of 'posts/__init__.py' will be:

        
            from .post import *
            from .posts_repository import *
        
    

And then I can use both classes as mentioned above. You can download examples of the above code in this zip. Of course, we could do the same in Ruby creating an intermediate ‘init’ file in posts directory, but Python’s way may be more semantic.

That's all for this week. It's been more writing than coding, but I think I understand Python’s packages and modules better