2019年7月に投稿した記事

【Python】構文のルール

今回はPythonの構文についておおまかにまとめます。

おそらく、触ってくると大体は分かってくる部分なのかなぁと思います。

まぁさくっと振り返ってみましょう!

ファイルの先頭から順に読込

基本的にファイルの上から下までプログラムは実行されていきます。一行は左から右に読み込みます。

文章と同じような読み込みの流れになります。

ただし、continueやbreak文、try文などはこの実行順序を変更します。

ブロックと文は自動で検出

Pythonでは字下げすることで、どの文が同じブロックに位置するかを示します。

とくに複合文がネストされている場合に、ぱっと見て構造がわかるような作りになります。

複合文は「:」を使用する

文には単純文と複合文の二種類あります。

単純文は1行で終わりますが、複合文はヘッダー部とボディ部に分かれているので1行では通常書きません。むりやり書くことはできますが、お勧めしません。

if/elif/elseやdef,class,with,tryなどが複合文に該当します。

どんな種類があったか確認したい方は以下を参照してください。

空白行とスペース、コメントは基本無視

通常、空白行に意味はありませんが、インタープリタでは意味があります。

インタープリタで複合文を書く場合に、その複合文が書き終わったことを明示しなければなりません。空白行はその書き終わったことをインタープリタに知らせる役割をもっています。

ファイルを編集して実行している場合、上記は関係ありません。

スペースは字下げや文字列リテラルとして構成される以外は無視されます。

コメントとしての#は文字リテラルの中以外は、#から始まり行末まで全て無視されます。

docstringは__doc__に格納

ファイルや関数、クラスなどのコードの先頭に置かれた文字列はドキュメンテーション文字列(docstring)と自動的に見なされます。

主に、このモジュールの役割、関数の詳細といったプログラマーにどのように使えばいいのかが書かれています。

ツールによって出力が可能なので、開発する時にはこまめに書いておくと、他の人や未来の自分自身にとってよいでしょう。

例として、以下のようにdocstringを書きます。

"""\
This is DocString.
ここに入っている文字列が__doc__に格納されます
"""

def test():
    '''
    ここに入っている文字列が属性testの__doc__に格納されます
    '''
    #test用の関数です.
    print('test')


if __name__ == '__main__':
    print(__doc__)
    print(test.__doc__)

~                                    

実行すると以下の結果が得られます。


This is DocString.
ここに入っている文字列が__doc__に格納されます


    ここに入っている文字列が属性testの__doc__に格納されます
    

注意点・Tips

字下げはタブでも可能

字下げはタブでもできます。
その場合でも同じブロックは同じように字下げをしましょう。

ただし、タブとスペースを混在させるのはNGです。以下のようなエラーが起こります。

>>> def indenterror():
...     tab = True
...     space_4 = True
  File "", line 3
    space_4 = True
                 ^
IndentationError: unindent does not match any outer indentation level

スペースを使うのかタブを使うのかはっきり決めて、どっちかだけ使いましょう。統一するほうがエラーが起きないです.

ただ、リッチなテキストエディタを使っている場合、勝手にスペースに補完してくれるので意識しないでも大丈夫なことが多いです。

単純文が1行で終わらないケース

単純文は基本的に1行で書けます。ですが例外的な書き方もあるのも事実です。

よく見かけるのは括弧で囲んで複数行に書く場合とトリプルクォーテーションで囲む場合でしょう。

括弧とは、(),{}, []で囲まれたものになります。これらは括弧が閉じられるまで何行でも書けます。
大抵、一行では長すぎるので複数行に分けていることが多いです。


def parentheses_test(name,
                     *args,
                     **kwargs
                    ):
    print(name)


args = ('one',
        'two',
        'three',
        'four',
        'five',
        )

args = ['one',
        'two',
        'three',
        'four',
        'five',
        ]

kwargs = {'one': 1,
          'two': 2,
          'three': 3
         }

トリプルクォーテーションは非常に長い文字列を簡単に扱うことができます。
主にhtmlやxmlを扱いたい時に使えますね。

from bs4 import BeautifulSoup

html = """
<!DOCTYPE html>
<html>
<head>
  <title>Hello World!</title>
</head>
<body>
  <h1>Full stack engineer from beginner </h1>
</body>
</html>
"""

bs = BeautifulSoup(html,'html.parser')
print(bs.h1)

また、バックスラッシュを行末に加えることでも一行とみなされます。
ですが、括弧で囲んだほうがいいでしょう。見にくいし。

x = 1000 + 3000\
         - 2000

x = ( 1000 + 3000
           - 2000
    )

複数の単純文を1行で書く

セミコロンを使えばできます。

print('Hey!'); print('this code'); print('just one liner!')

ですが、あまりお勧めしません。
一行一行書いたほうが明快で見やすくなります。

まとめ

いかがだったでしょうか?

結構重箱の隅をつつくような内容だったかもしれません。

そもそも、タブとスペースが混在したケースとか、一行に詰め込んだ書き方とか見たことありませんし。。

まぁ、知識として覚えておいてもいいと思います!
いつか、後進を育成する時に使うかもしれませんしね。

それでは今回は以上になります。

みなさんのPythonライフが向上することを祈っています!

【Python】break文

今回はbreak文についてまとめます。

break文はほとんど他の言語と同じような動作をします。最も内側にあるループから抜け出すという動作です。

ほとんど同じなのですが、elseブロックと組み合わせることができるのがPythonならではの特徴だと思います。

それでは見ていきましょう!

break文とは

最も内側のループを無条件で抜けます。

また、その特性上、for文やwhile文といったループの中でしか使えません。これはcontinue文と同様です。

上手に使うことで文のネストを減らすことができます。

break文の用法

breakの使い方は非常にシンプルです。ループの中で使います。
Pythonの場合、ループはfor文やwhile文の2つしかないので、この中でしか使えません。

それでは下のコードを見てみましょう。

for x in range(1, 10):

    if x == 6:
        break

    print(x)
print('well done')

実行すると以下の結果になります。

1
2
3
4
5
well done

6以降の数字は表示されていませんね。
ループを終了してループ外のprint(‘well done’)を実行していることが分かります。

それでは次のコードはどうでしょうか?

for x in range(1, 3):

    y = 0
    while y < 5:

        print(x, y)

        if y == 2:
            break

        y += 1

print('well done')

ループが入れ子(ネスト)されていますね。
この場合の実行結果は以下になります。

1 0
1 1
1 2
2 0
2 1
2 2
well done

そうです。break文は一番内側のループを抜け出すのです。

あくまでwhile文を抜ける処理になりますので、for文は続いていることが分かると思います。

elseとの組み合わせ

break文はelseブロックと組み合わせることができます。

elseブロックはループが正常に終了した場合に実行されます。break文でループを強制的に終了された場合は実行しません。

以下のコードを見てみましょう。

for x in range(1, 5):

    if x == 3:
        break
    print(x)

else:
    print('Ok it is not break')

print('well done')

実行結果は以下になります。

1
2
well done

for文内でbreak文が実行されていますので,else文が実行されていません。

これはPythonに特有なコードで、breakせずに正常終了したかどうかをelseブロックを用いることで簡潔に表現できます。

他の言語ではこのようなことはできません。なにかしらのフラグを立てる必要があります。

まとめ

いかがでしょうか。

break文はcontinue文と非常に似ています。
ループ中の流れを変更し、別の位置にジャンプさせます。

また、breakに特有なのがelseブロックと組み合わせた時の動作です。
breakによって終了したかどうかを検査する場合に効果を発揮します。

以上になります。

みなさんのPythonライフが向上するように祈っています!

【Django】AWSでPostgresqlとの連携

題目どおりにAWS上でDjangoをPostgresqlに繋ぐためのフローをまとめています。

あまり説明はしませんが、どのように作成すればいいかの指針になるといいなと思います。

実行環境

今回使用するのはcloud9を使います。使用するのはAmazon Linuxです。

まっさらな環境から構築いたします。

環境は以下になります。

FSE:~/environment $ uname -a
Linux ip-172-31-32-133 4.14.123-86.109.amzn1.x86_64 #1 SMP Mon Jun 10 19:44:53 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux

また、その他の環境は以下でした。

(project_db) FSE:~/environment/project_db $ psql --version
psql (PostgreSQL) 9.2.24
(project_db) FSE:~/environment/project_db $ django-admin --version
2.2.3

Postgresqlの準備

まずは、postgresqlの環境を整えます。

以下のコマンドでpostgresqlをインストールとしてください

sudo yum -y install postgresql postgresql-server

インストールできたことを確認するために以下のコマンドでバージョンを確認しましょう。

FSE:~/environment $ psql --version
psql (PostgreSQL) 9.2.24

Postgresqlのサーバーを立ち上げる

Postgreは使用する前に初期化する必要があります。
以下のコマンドを実行してください。

FSE:~/environment $ sudo service postgresql initdb
Initializing database:                                     [  OK  ]

Postgreサーバーを立ち上げましょう。
以下のコマンドを実行してください。

FSE:~/environment $ sudo service postgresql start
Starting postgresql service:                               [  OK  ]

正常に立ち上がったことを確認するためにログインしてみましょう。
以下のコマンドで確認してください。

sudo -u postgres psql -U postgres
could not change directory to "/home/ec2-user/environment"
psql (9.2.24)
Type "help" for help.

postgres=# 

postgresのコマンドプロンプトがでているので成功になります。

Postgresqlでユーザ登録

Postgresqlの初期設定ではpeer認証となっていますので、ec2-userのロール及びDBがないとpostgresユーザを使わなければなりません。

以下のコマンドでec2-userを作成してください.

FSE:~/environment $ sudo -u postgres createuser ec2-user
could not change directory to "/home/ec2-user/environment"

さらにPostgresqlではユーザ名と同じDBが必要になります。
以下のコマンドでec2-userというデータベースを作ります。

FSE:~/environment $ sudo -u postgres createdb ec2-user -O ec2-user
could not change directory to "/home/ec2-user/environment"

-Oはオプションで、データベースの所有者を指定します。今回はec2-userにしています。

それでは、ユーザーが作成できていたのかを確認します。


FSE:~/environment $ psql
psql (9.2.24)
Type "help" for help.

ec2-user=> select * from pg_user;
 usename  | usesysid | usecreatedb | usesuper | usecatupd | userepl |  passwd  | valuntil | useconfig 
----------+----------+-------------+----------+-----------+---------+----------+----------+-----------
 postgres |       10 | t           | t        | t         | t       | ******** |          | 
 ec2-user |    16389 | f           | f        | f         | f       | ******** |          | 
(2 rows)


ec2-userが登録されていることが確認できますね。
終了するには、「\q」もしくはCtrl + Dを押してください

それではDBが作成されているかを確認します。


FSE:~/environment $ psql -l
                                  List of databases
   Name    |  Owner   | Encoding |   Collate   |    Ctype    |   Access privileges   
-----------+----------+----------+-------------+-------------+-----------------------
 ec2-user  | ec2-user | UTF8     | en_US.UTF-8 | en_US.UTF-8 | 
 postgres  | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | 
 template0 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +
           |          |          |             |             | postgres=CTc/postgres
 template1 | postgres | UTF8     | en_US.UTF-8 | en_US.UTF-8 | =c/postgres          +
           |          |          |             |             | postgres=CTc/postgres
(4 rows)


ec2-user というデータベースが正常に作成されていますね。

もしdjangoで別のユーザとデータベースを作成する場合は同様にユーザーとデータベースを作成します。

今回は以下のように設定しています。


sudo -u postgres createuser test_user
sudo -u postgres createdb test_db -O test_user

ユーザのパスワードを設定する

認証方式を変更する前にユーザにパスワードを設定しておきましょう。

これも権限が必要なのでpostgresとしてpsqlを起動しています。


FSE:~/environment $ sudo -u postgres psql
could not change directory to "/home/ec2-user/environment"
psql (9.2.24)
Type "help" for help.

postgres=#

ユーザのパスワードを設定しましょう。


postgres=# ALTER USER test_user  WITH ENCRYPTED PASSWORD 'test_password';
ALTER ROLE

上記ではtest_userに対してtest_passwordを設定しています。

ここで設定したユーザー名とパスワード及び、DB名はDjangoで使用しますので覚えて起きましょう。

Postgresqlの認証方式を変更する

認証方式を変更するには、pg_hba.confのファイルの内容を変更する必要が有ります。

まずは、そのファイルの場所を調べましょう。
以下のコマンドを実行してください。

FSE:~/environment $ sudo -u postgres psql -q
could not change directory to "/home/ec2-user/environment"
postgres=# show hba_file;
             hba_file             
----------------------------------
 /var/lib/pgsql9/data/pg_hba.conf
(1 row)


私の場合は/var/lib/pgsql9/data/pg_hba.confにあるようです。

それでは編集のために以下を入力してください

sudo vi /var/lib/pgsql9/data/pg_hba.conf

このファイルを編集するためには権限が必要ですので、必ずsudoを付けてください。

ファイルの下のほうに以下のような記述が有ります。


# IPv4 local connections:
host    all             all             127.0.0.1/32            ident

以下のように変更してください。
identtrustにしています。


# IPv4 local connections:
host    all             all             127.0.0.1/32            md5

設定ファイルを変更したのでサーバーを再起動します。

FSE:~/environment $ sudo service postgresql restart
Stopping postgresql service:                               [  OK  ]
Starting postgresql service:                               [  OK  ]

Djangoをインストールする

まずはプロジェクトとなるディレクトリを作り、移動します。

FSE:~/environment $ mkdir project_db && cd project_db
FSE:~/environment/project_db $ 

pipのバージョンを上げておきます。

FSE:~/environment/project_db $ sudo pip-3.6 install --upgrade pip

pipenvをインストールします。
私の場合は権限によるエラーが出たので–userオプションを指定しています。


FSE:~/environment $ pip3 install pipenv --user

pipenvでdjangoをインストールします。


FSE:~/environment/project_db $ pipenv install django==2.2.3

pipenvを起動します。

FSE:~/environment/project_db $ pipenv shell
Launching subshell in virtual environment…
FSE:~/environment/project_db $  . /home/ec2-user/.local/share/virtualenvs/project_db-ixZ6iYXw/bin/activate
(project_db) FSE:~/environment/project_db $ 

pipenvを起動すると左側でディレクトリを丸括弧で囲んで表示されるので、分かりやすくなっています。

Djangoプロジェクトの設定

それではDjangoのプロジェクトを作成します。
最後のドットに気をつけてください。

(project_db) FSE:~/environment/project_db $ django-admin startproject db_connection . 

ちなみにドットがあると、プロジェクトファイルを作成せずにその場でファイルを展開します。

以下のコマンドで設定ファイルをいじります。

(project_db) FSE:~/environment/project_db $ vi db_connection/settings.py 

設定を変更する場所は2点あります。
ALLOWED_HOSTSとDATABASESです。それぞれ見ていきましょう。

ALLOWED_HOSTS

初期値だと[]になっています。

ローカル接続の場合は[]で大丈夫ですが、cloud9の場合は状況が違います。
接続できるように、指定してあげましょう。

よく分からない人は以下でも大丈夫です。

ALLOWED_HOSTS = ['*']

DATABASES

初期設定ではsqlite3をdjangoは使用します。

従って、ここをpostgresql用に変更します。
初期設定は以下になります。


DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}


上記を以下に変更します。


DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'test_db', #DB名 
        'USER': 'test_user', #USER名
        'PASSWORD': 'test_password', #PASSWORD
        'HOST': 'localhost', #接続HOST
        'PORT': '5432', #接続ポート 省略可
    }
}


Djangoを起動

最後にPythonがpostgresqlにアクセスするためのモジュールとしてpsycopg2-binaryをインストールします。

(project_db) FSE:~/environment/project_db $ pip install psycopg2-binary

それではDjangoをマイグレートしましょう!

(project_db) FSE:~/environment/project_db $ python3 manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying admin.0003_logentry_add_action_flag_choices... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying auth.0009_alter_user_last_name_max_length... OK
  Applying auth.0010_alter_group_name_max_length... OK
  Applying auth.0011_update_proxy_permissions... OK
  Applying sessions.0001_initial... OK

成功しましたね。

それでは最後にサーバーを立ち上げて、画面を表示してみましょう。

(project_db) FSE:~/environment/project_db $ python3 manage.py runserver 8080

晴れて、DBに接続してDjangoが使えるようになりました!

注意点・Tips

psycopg2

psycopg2は2.8からリネームしてpsycopg2-binaryになっていることに注意してください。

これに気づかず嵌りました。

まとめ

djangoの設定自体はそんなに難しくないと思います。ただ、postgresqlのサーバーの立ち上げやユーザーの作成が意外にめんどくさいことがわかりました。

ec2-userを作成したのは、psqlコマンドでいちいちアクセスできないのが面倒だったからです。権限を追加すればsudoコマンドは必要なくなると思います。

以上になります。

長々とお付き合いありがとうございました!

【Python】continue文について

今回はcontinue文についてまとめます。

これは他のプログラミング言語と同じ動きになりますので、経験者の方はスキップしても全然構いませんよ!

それではみてきます。

continue文とは

continue文は最も内側のループの先頭まで即座に戻ります。for文とwhile文で使用することができます。

ある意味でgoto文で似ている処理になります。goto文とはC言語などである処理に無条件でジャンプする処理です。continueはループの先頭まで処理をジャンプさせることができます。

従って、goto文が嫌われるように、コードの保守が難しい一面も備えています。なので、適切な使用が求められます。 

適切に使えれば、文のネストの回数を減らせることができます

ネストというのは、構造の中にさらに構造を入れることです。Pythonならfor,while,if文などを入れ子にすることです。これをし過ぎると読みにくくて嫌われます。

continue文の用法

それでは実際にcontinue文を使ってみましょう。

使い方は非常にカンタンです。以下のコードを見てください。


>>> for x in range(0,10):
...   if x % 2 == 0:
...     continue
...   print(x)
... 
1
3
5
7
9

このコードはxが奇数の時だけコンソールに出力するプログラムです。

偶数の場合は即座にループの先頭に戻り、次の数字を取得しています。

それでは次の場合はどうでしょうか。


>>> for y in range(1,10):
...   if y > 6:
...     continue
...   for x in range(1,10):
...     if x > 7:
...       continue
...     if x * y % 6 != 0:
...       continue
...     print(f'{y}:{x}')
... 
1:6
2:3
2:6
3:2
3:4
3:6
4:3
4:6
5:6
6:1
6:2
6:3
6:4
6:5
6:6
6:7

うまいコードが書けないのはご愛嬌ということで;)
とりあえず見てほしいのは、for文がネストされているときにどうなっているかです。

そうです。continue文は最もfor文が近い場所にジャンプしているのです。

最も内側のループにジャンプすることさえわかれば、continue文はほぼマスターしたことになります。

まとめ

いかがでしょうか。

やり方さえわかってしまえば、あとはどのように使うかのほうが難しいと思います。

私もまだまだ修行中なので頑張っていきましょう!

それでは今回は以上になります。

みなさんのPythonライフがより良くなるように祈っています!

【Python】pass文について

今回はpythonのpass文についてまとめています。

これは実際のコードよりもチュートリアルの本でよく見る気がしますね。

先に結論から言うと、 用法としては以下の2点になると思います。

pass文の用法

  1. 処理を後で記述するために
  2. 条件判定式で書くべき処理がない

それではみてきましょう!

pass文の用法

pass文はプレースホルダーとしての役割があります。

複合文はヘッダー部とボディ部から構成されます。このヘッダー部とボディ部は必ず必要になります。

ボディ部を書かないとPythonの構文上、エラーになってしまいます。


>>> def function(arg1, arg2):
... 
  File "", line 2
    
    ^
IndentationError: expected an indented block

IndentationErrorとなっていますね。
内容は、「インデントされたブロックを想定しています」となります。つまり、インデントしてボディ部を構成してくださいというわけです。

処理を後で記述するために

pass文はこのsyntax errorにならないよう、とりあえず場所をとっておいてくれます。


>>> def function(arg1, arg2):
...   pass
... 
>>> 

基本的にはプレースホルダーの役割として、Pythonの構文エラーにならないように入れます。モックを書いている場合でも明示的に飛ばしていることをPythonに知らせる必要があります。

条件式で書く処理がない場合

複雑な条件で当てはまったら処理をしない場合にも同様に使えます。

これはサンプルコードとしてはこんな感じでしょうか。

>>> import random
>>> X = random.random()
>>> if X < 0.3:
...   pass
... elif 0.3 <= X < 0.5:
...   print('middle value')
... else:
...   print('big value')
... 
big value

これは簡単な例として、0.3未満の値だったら何も表示したくない場合に、passを用いています。

まとめ

いかがでしょうか。おそらくそんなに難しくなかったと思います。

Pythonは明示的に書くほうが好ましいとされます。

その考えで言えば、処理を書かないことを明示するのは言語として望ましいのではないでしょうか。

間違いも分かりやすいですしね。

それでは今回は以上になります。

みなさんのPythonライフが向上するように祈っています!

【Python】複合文の種類

Pythonの文には単純文と複合文の2種類有ります。

そのうちの複合文はヘッダー部分とボディ部分から構成される文です。通常は、2行以上で書かれます(もちろん例外は有ります)。

今回は複合文の種類について例示だけします。
それぞれの詳しい使い方は必要に応じて記事にしたいと思います。

種類
if/elif/else文if 条件: … elif 条件: … else:
while文while 条件:
try文try: 処理
with/as文with リソース as 変数:
関数定義def func(args,*args,**kwargs):
クラス定義class ClassName(SuperClass):
コルーチン関数定義async def func(args, *args, **kwargs):
async for文async for item in items:
async with文async with リソース as 変数

注意点・Tips

Pythonの仕様変更

Python2.5からtry/exceptとtry/finally文が統合されました。

Python2.6からwith/as文が追加されています。
これはtry/finallyの代替として設計されています。

Python3.5からコルーチンの概念が正式に実装され、コルーチンに関係するasync文が追加されています。

まとめ

今回の記事の詳しい説明は以下に載っています。

参考: 複合文 (compound statement)

また、さらに一つ一つ記事にしていきますのでどうぞよろしくお願いしますね!

以上になります。みなさんのPythonライフがよりよくなるように祈っています!