カテゴリー「python」の8件の記事

2020-07-27

python requests.exception.SSLError SSL接続でエラーが出る

pythonでrequestsを使ってウェブアクセスすると
以下のエラーが出てデータを取得できない。
requests.exceptions.SSLError
(Caused by SSLError(SSLError(1, '[SSL: DH_KEY_TOO_SMALL] dh key too small (_ssl.c:1056)')))

調べてみるとrequestsでgetやpostする前に
requests.packages.urllib3.util.ssl_.DEFAULT_CIPHERSに
足りない文字列を追加してやればいいらしい。

requests.packages.urllib3.util.ssl_.DEFAULT_CIPHERS += "HIGH:!DH"

調べた内容には"HIGH:!DH:!aNULL"を追加する
というような記事があった。
自環境のssh_.pyを確認してみると!aNULLは記載されていたのでHIGH, !DHのみ追加した。

| | コメント (0)

2016-10-21

Python+mysqlconnectorでのサニタイジング(エスケープ)

mysql.connectorでのサニタイジング

サニタイジングは*浄化*の事で、文字通りにデータを浄化します。

なぜサニタイジングが必要?

データベースを操作する、ほとんどのアプリはユーザーに検索条件などを入力させると思いますが、この時、検索条件に悪意のあるSQL文を書かれてしまって、意図しない情報を出力してしまう事を避けたり、記号の混入などで思わぬエラーを避けるためにサニタイジングが必要になります。

詳しくは*SQLインジェクション*のキーワードで検索してみてください。

サンプル

エスケープする手段はmysql.connector側で用意してくれていました。

cursor.execute()のパラメータにqueryとデータを渡します。つまり、データをクエリの中に埋め込まずに、クエリにはフォーマットのみを書き、データは別に渡します。すると、execute()でフォーマットしてから実行してくれます。

続きを読む "Python+mysqlconnectorでのサニタイジング(エスケープ)"

| | コメント (0) | トラックバック (0)

2014-09-13

Python CGIでウェブアプリを作ってみる その1

最近、Pythonを勉強し始めた訳だが、偶然知り合った方が作ったウェブアプリがPython2.7で書かれたということで、PythonでのCGIが気になったのでやってみました。

自宅で、テスト用というか遊び用に使っている古いLinux機でやったので、Pythonのバージョンは2.4.4です。現在の標準的な文字コードはUTF-8だと思いますが、私の環境ではEUC-JP環境なので、環境に応じた文字コードに置き換えて読んで下さい。

今回はとにかく、インプットとアウトプットの方法を確認しておきたいと思います。

sample1.cgi
#!/usr/bin/python
# -*- coding: euc-jp -*-

import site
import cgi
import os

print "content-type: text/html\n\n"

print '<html>'
print '<head><meta charset="euc-jp"></head>'
print '<body>'
print '<h1>CGIサンプル</h1>'
print '<form action="sample1.cgi" method="get">'
print 'メッセージ <input type="text" name="msg">'
print '<input type="submit">'
print '</form>'

# formで送信される方法を取得して出力してみる
if os.environ['REQUEST_METHOD'] == 'POST':
    print 'POST'
elif os.environ['REQUEST_METHOD'] == 'GET':
    print 'GET'

print '<br />'

# 入力された値を出力する
form = cgi.FieldStorage()
if form.has_key('msg'):
    print '<h2>' + form['msg'].value + '</h2>'

print '<body>'
print '</html>'

実行結果
Python_cgi_sample

取り敢えず、ちょこちょこっとネットで検索して、こんな感じで書いて動かしてみましたが、いちおう意図通りにデータを取得して表示できているようです。

入出力に関する処理さえできてしまえば、後は通常のローカルで動作するアプリケーションと同じなので、入力値を処理して出力するという事になると思います。
データベースとの連携、ファイルの入出力。これらは複数のプロセスからアクセスされる事があるので、排他処理が重要になってくると思います。
他にはセッションの管理とかクッキーなどの処理ができると、より使い勝手の良いアプリケーションができると思いますので、今後その辺りも探ってみたいと思います。
現段階で予備知識は全くありませんので、手探りで調べながら楽しみたいと思います。



| | コメント (0) | トラックバック (0)

2014-08-30

PythonでKInterbasDBを使ってFirebirdデータベースに接続してみる

KInterbasDBのダウンロード / インストール

Windowsは7と8で両方とも64bitです。Pythonバージョンは2.7なのでkinterbasdb-3.3.0.win-amd64-py2.7.msiをダウンロードしてインストール。

Linuxはkinterbasdb-3.3.0.tar.bz2をインストールしました。

tar xzvf kinterbasdb-3.3.0.tar.bz2
cd kinterbasdb-3.3.0
python setup.py install

接続テスト

古いLinux機を使っているため文字コードがEUC-JPです。
また、使用しているfirebirdは1.5です。
pythonのバージョンは2.4です。

Windows 7と8.1の64bitでも、同じような方法で接続できました。
Python2.7firebird 2.1です。

# -*- coding: euc-jp -*-

import site
import kinterbasdb

def test_conn():
    con = kinterbasdb.connect(dsn='127.0.0.1:/var/gdb/test.gdb',
                              user='sysdba',
                              password='masterkey')
    cur = con.cursor()
    cur.execute('SELECT FIRST 20 ID, TITLE FROM TEST_TBL ORDER BY ID DESC')
    rows = cur.fetchall()
    for (id, title) in rows:
        print '%d\t%s' % (id, unicode(title, 'euc-jp'))
        # Windowsなどでは以下の
        # print '%d\t%s' % (id, unicode(title))
        # で動くと思う
    cur.close()
    con.close()

if __name__ == '__main__':
    test_conn()

14行目の出力の部分は、データベースに格納されているデータの文字コードとの関係があると思います。私の環境ではunicode(titie)ではエラーが出てしまったので、'euc-jp'を渡していますが、Windows環境でデータの文字コードをUNICODE_FSSに指定した環境ではunicode(title)だけで正常に出力してくれました。

レコードをフィールド名と値のディクショナリで取得する

ディクショナリで取得するにはfetchallmap()など、fetch*メソッドにmapをつけるとディクショナリで取得できるようです。実際にやってみました。

# -*- coding: euc-jp -*-

import site
import kinterbasdb

def test_conn():
    con = kinterbasdb.connect(dsn='127.0.0.1:/var/gdb/test.gdb',
                              user='sysdba',
                              password='masterkey')
    cur = con.cursor()
    cur.execute('SELECT FIRST 20 ID, TITLE FROM TEST_TBL ORDER BY ID DESC')
    rows = cur.fetchallmap()
    for fields in rows:
        print '%d\t%s' % (fields["id"], unicode(fields["title"], 'euc-jp'))
        # Windowsなどでは以下の
        # print '%d\t%s' % (id, unicode(title))
        # で動くと思う
    cur.close()
    con.close()

if __name__ == '__main__':
    test_conn()


| | コメント (0) | トラックバック (0)

pythonでMySQL Connectorを使ってデータベースに接続してみる

MySQLに接続してみました。

MySQL connector/Pythonのダウンロード

まずはMySQLのサイトからPython用のコネクターをダウンロードします。

MySQL connector/Pythonのインストール

Windows版はWindowsインストーラで配布されているので、インストーラでインストールするだけだと思います。私は古いLinuxにインストールしたかったのですが、Ubuntu, Debian, SUSE, Red Hatのどのディストリビューションでもないので、Platform Independentを選択してtar.gz形式からインストールしました。

tar xzvf mysql-connector-python-1.0.12.tar.gz
cd mysql-connector-python-1.0.12/mysql-connector-python-1.0.12
python setup.py install

という感じでtarファイルを展開して、setup.pyファイルをinstallパラメータ付きで実行してインストールしました。ファイル/フォルダ名のバージョン番号は利用するバージョンによって変わってくると思います。私の環境ではpythonのバージョンが2.4なので敢えて古いバージョンを選択しました。
Windowsにはpython2.7をインストールしてコネクターは1.2.3をインストーラでインストールしました。

WindowsやUbuntuで利用するなら特に悩むこともなくインストールできるのだと思います。

接続テスト

さっそく、キチンとインストールできたのか、MySQLにアクセスできるかをテストしてみました。

古いLinux機でやったため、システムもデータベースも文字コードがEUC-JPなので文字コードに関する処理の部分が最近の一般的なシステムとはちょっと違ってると思いますので、適宜UTF-8やUnicodeでの処理に置き換えて下さい。

# -*- coding: euc-jp -*-

import site
import mysql.connector

def test_con():
    connect = mysql.connector.connect(user='root', 
                                          password='passwd', 
                                          host = '127.0.0.1', 
                                          database='TestDB', 
                                          charset='ujis')
    cursor = connect.cursor()
    cursor.execute('SELECT ID, TITLE FROM TEST_TBL ORDER BY ID DESC LIMIT 5')
    rows = cursor.fetchall()
    for (id, title) in rows:
        print '%d\t%s' % (id, unicode(title))
    cursor.close()
    connect.close()

if __name__ == "__main__":
    test_con()

14行目のrowsにはタプルが格納されたリストとして返されるようで、リストの1要素が1レコードで、タプルの1要素が1フィールドに対応しているようです。

レコードの内容をディクショナリで取得する

調べてみたら、どうやらMySQL connectorのDevelopment Releasesとなるバージョン2.0.0からはコネクターからカーソルを取得する時にdictionary=Trueとする事でディクショナリのリストとして結果を取得できるようです。

    connect = mysql.connector.connect(user='root', 
                                          password='passwd', 
                                          host = '127.0.0.1', 
                                          database='TestDB', 
                                          charset='ujis')
    cursor = connect.cursor(dictionary = True)
    cursor.execute('SELECT ID, TITLE FROM TEST_TBL ORDER BY ID DESC LIMIT 5')
    rows = cursor.fetchall()
    for fields in rows:
        print '%d\t%s' % (fields["ID"], unicode(fields["TITLE"]))
    cursor.close()
    connect.close()

こんな感じになるんでしょうかね。試してませんのであしからず。

フィールド名と値のディクショナリになってると、SQLの内容やフィールドの順序を知らなくても、フィールド名で値にアクセスできるので便利です。

MySQL for Python

今回テストしたモジュールではないMySQL接続モジュールです。もしかするとこちらのモジュールを使われている方の方が多いのかな。

MySQL for Python ( http://sourceforge.net/projects/mysql-python/ )


続きを読む "pythonでMySQL Connectorを使ってデータベースに接続してみる"

| | コメント (2) | トラックバック (0)

2014-08-28

Authentication with old (insecure) passwords is not supported. For more information, lookup Password Hashing in the latest MySQL manual

せっかく始めたので、データベースにアクセスしたいとMySQL connector Pythonを使ってみた。

Authentication with old (insecure) passwords is not supported. For more information, lookup Password Hashing in the latest MySQL manual

随分古いLinuxでもWindows 8.1でも2台のサーバーのMySQLに接続できているのに、同じソースで何故か一台のコンピュータからだけ接続できずに上記のようなエラーが出ていた。

サポートされていないって言われても、別のクライアントからは同じバージョンのツールでアクセスできてるんだから、できないってことは無いでしょうがよ!

で、結論から書くと一台のサーバーだけ、なぜかHost指定でユーザーが登録されており、そのIPがたまたま今回接続しようとしているコンピュータのIPだった。クライアント側はDHCPからアドレスを取得しているので、本当にたまたまだった訳で、なぜこのホストからだけのユーザーを登録したのかも全然わからないのだが、多分、サーバーを稼働し始めた当時に色々と実験をしていた物が残っていたのだと思う。

他のコンピュータからは同じデータベースに同じユーザー名とパスワードでアクセスできるのに、どうしてかと散々悩んだが、最初からサーバー側を確認すればよかった。クライアント側だけでどうにかできんもんかと悩んでしまった。

まぁ、MySQLとFirebirdにアクセスできれば、自分としてはかなり便利に使えるのでありがたい。

| | コメント (0) | トラックバック (0)

2014-08-26

QpytonでKivyを使ってGUIアプリのサンプルを書いてみた

Androidで動作するPythonQPythonを使ってみました。
Python自体、始めて3日位なので…。

import kivy

from kivy.app import App
from kivy.uix.label import Label
from kivy.uix.button import Button
from kivy.uix.boxlayout import BoxLayout

class MyApp(App):
    def exit_wnd(self, *args):
        App.stop(self)

    def build(self):
        layout = BoxLayout(padding=10,orientation="vertical")
        exit_btn = Button(text = 'exit')
        exit_btn.bind(on_press=self.exit_wnd)
        layout.add_widget(Label(text = 'Hello, World'))
        layout.add_widget(exit_btn)
        return layout

if __name__ == '__main__':
    MyApp().run()

1408998460678.jpg

1408998187862.jpg

イベントハンドラのexit_wndに渡してる*argsがどう使われるのか、いまいち理解してないけど…。

続きを読む "QpytonでKivyを使ってGUIアプリのサンプルを書いてみた"

| | コメント (0) | トラックバック (0)

2014-08-25

pythonで二つの変数の値を交換(swap)する

最近、なんとなくリフレッシュしようと前から興味のあったpythonをいじってみました。

で、swap関数が標準であるのかどうかもわからず、自作しようかと思ったのですが、参照渡しの方法がわからず、調べてみるとpythonには参照渡しが無いとのこと。

で、複数の値の代入ができることを学びました。リストとして扱っているのでしょうかね。

なので、ブログに書くまでのこともなく、簡単に交換できるのですが、自分用の覚書として書いておきます。

a = 10
b = 99

a, b = b, a

print a # 99を出力
print b # 10を出力
となるようです。
def gcd(a, b):
    while a != b:
        if b > a:
            a, b = b, a
        a -= b
    return a

if __name__ == "__main__":
    print gcd(72, 16)

とかで、いいっぽいです。

実行してみるときちんと8が出力されました。

> python gcd.py
8

| | コメント (0) | トラックバック (0)