Subscribed unsubscribe Subscribe Subscribe

Anacondaから標準のPythonに

Raspberry Pi 3にPythonの環境を構築してて思ったのですが、環境構築ってAnacondaじゃなくてもよくない?と思ったのでAnacondaから標準のPythonに移行しました。環境はMacで行っております。

まずhomebrewをインストールします。この手順は他サイトで紹介されていると思うので探してみてください。

brew install python3

とするとPython 3系がインストールできます。Pythonがインストールできたらpip3コマンドが使えるので必要なライブラリをそれぞれインストールしたらおしまいです。自分はnumpy, scipy, matplotlib等をインストールしました。

pip3 install numpy scipy matplotlib

こんな感じです。

仮想環境も作れると思ったのでつくてみたのですがなんかエラーが出ました。めげずにもう一回同じコマンドを打つと仮想環境が構築できました。結果仮想環境が作れたのでいいのですが、なぜエラーがでるのか少し気になりますね。

Pythonの仮想環境構築

最近Raspberry Pi 3でwebアプリを作ろうと奮闘しております。システムにインストールされているPythonと分別する意味でも仮想環境下にPython環境を構築したほうが良いという情報をよく目にしたため、仮想環境の構築と日頃使っているライブラリのインストールを行いました。環境はUbuntu MATE 16.04で行っております。

そもそも仮想環境とは

あくまで自分の理解の範疇で書きます。間違っている点も多々あると思いますのでその点はご了承ください。

そもそもPCでコマンドが使用できるのは/bin以下に使用したいコマンドのバイナリファイルがあるためです。普通に使用する分にはいわゆる普通のインストール(バイナリファイルが/bin以下に格納される)をすれば良いです。しかし/bin以下にインストールされたコマンドはシステム全体で利用されるためシステムのPython環境を汚染します。具体的にはライブラリのコンフリクト等が起きるのではないかと思われます。こういった事態を避けるためにシステムとはまた別の環境を作り、その環境にPythonをインストールすることでシステムのPython環境を汚染することなくPython環境を構築することができます。

Ubuntuに仮想環境を構築する

現在Raspberry Pi 3にUbuntu MATE 16.04をインストールしサーバーとして使っています。このマシンにPythonの仮想環境を構築しました。Ubuntu MATE 16.04にはデフォルトでPython3.5が入っており、Python3.5ではvenvというモジュールを用いて仮想環境を構築します[1]。仮想環境を構築したいディレクトリに移動、もしくはディレクトリを作製し、そのディレクトリ以下に仮想環境を構築します。以下ではhogeというディレクトリを作製し、そこに仮想環境を構築しています。

mkdir ~/hoge
python3 -m venv ~/hoge

これで~/hoge以下に仮想環境が構築されました。この仮想環境をアクティベートするには

source ~/hoge/bin/activate

コマンドを打ちます。 するとプロンプトが

user@machine:~$

から

(hoge) user@machine:~$

となります。UbuntuのシステムにはPython2とPython3のどちらもインストールされているのでPythonのバージョンを指定して起動するためにpythonとするとPython2がpython3とするとPython3が起動するようになっています。しかし構築した仮想環境をアクティベートすると仮想環境下にはPython3のみがインストールされており、pythonと打つだけでPython3が起動するようになります。同様にシステムのPython環境ではpipでPython2のライブラリのインストールが、pip3でPython3のライブラリのインストールができますが、仮想環境下ではpipでPython3のライブラリがインストールされます。自分はここで詰まったので一応書いておきます。

またよく使っているPythonライブラリのnumpy, matplotlibをインストールしました。

(hoge) user@machine:~$ pip install numpy

とするとnumpyがインストールされました。 同様に

(hoge) user@machine:~$ pip install matplotlib

とするとmatplotlibがインストールされるかと思いきやエラーが出ました。

エラーログを読んでみるとfreetypepngというライブラリが必要だけど入ってないよという内容でした。ここで注意するべきはfreetypepngPythonのライブラリではなく、システムにインストールするライブラリです。ここでも自分は詰まりました…笑

sudo apt install freetype png

とするとどうもそのような名前のライブラリはないよということを言われました。 そこで[2]を参考にpngを、[3]を参考にfreetypeをインストールするとmatplotlibのインストールができました。

さらっと書いてはいますがmatplotlibのインストールするだけで2, 3日かかってます笑

参考と轍づくりのために書いておきました。それでは。

[1] 28.3. venv — 仮想環境の作成 — Python 3.6.1 ドキュメント
[2] Ubuntu15.04でpipでMatplotlibがインストールできない件 - python3.4から始めるプログラミング日記
[3] matplotlibのインストールでつまづいた話 - Qiita

Raspberry Pi 3 & ubuntu server

ラズパイ3にubuntuサーバーを導入して自宅サーバを構築しようと試みているのですが、再起動するとLinux kernel starting…という表示から起動しなくなります。正直ここまでハードウェアに近いことに興味があまり持てないのでこういうトラブルはやる気が削がれる一方です。公式が出してるubuntu MATEをサーバーみたいに使うほうが初心者にはいいのでしょうか。Pythonでwebアプリをつくってみたいだけなのに、そのはるか手前で躓いていて果たしていつその目標を達成できるのやら…

ブログと言うかTwitterで呟けばいいようなことではあるのですが、書いてみました。

2017/05/09追記 ubuntu MATEをインストールしてコンソールモードで使うことにしました。公式が出しているだけあってwifiもはじめから認識しているのでハードウェア的なことに煩わされないで済みます。初心者にはこっちの方がいいかもしれないですね。

新しいAnaconda

Pythonの環境づくりにpyenvとAnacondaを利用しております。一年ほど闇雲にインストールしたままでPythonを利用してきたのですが、さすがにそのまま使い続けるのもどうかと思ったので新しくインストールし直しました。

そして先日組んだGUIプログラムを起動させようとするとなんと起動しないではないですか。エラーメッセージを読んでみるとどうやら新しいAnacondaにはPyQt4が入っていないようでPyQt5に完全移行されたみたいです。それならとPyQt4と書いてある部分をPyQt5に書き換え起動させようとするとこれもまた起動しません。なんでかなーと思いちょっと調べてみるとどうやらPyQt4とPyQt5ではインスタンスのある場所が変わっているようで、widget系のインスタンスはQtWidgetsというところに移動したようです。なのでQtGuiから呼び出していた部分をQtWidgetsに書き換えたところ無事起動できましたとさ。

それだけの記事なのですが一応道標として…

keynoteの色の指定

大学の研究においてデータプロットはpythonのmatplotlibを用いています。matplotlibは使い慣れていることもあってわりと便利なのですが、ピーク検出等を全自動で行うとどうしても精度が良くない時があります。そんなときはデータを見つつマーカーをつけたりと手動でグラフ作成を行っており、そのときの画像編集はkeynoteを使っています。しかしそういった場合matplotlibのプロットした線とマーカーの色が異なってしまうことが多々あります。そこでkeynoteで16進数での色指定ができないかと調べていたところ意外とあっさりできました。

やり方としてはまず何かしらのオブジェクトを追加します。そしてそのオブジェクトがアクティブなときにカラーパネルのようなところをクリックします。

f:id:jinpei0908:20170426225941p:plain

次に2つめのタブのRGB sliderを選択します。一番下のHex Colorのところに16進数で値を入力するだけです。

f:id:jinpei0908:20170426225954p:plain

またmacにはdigital color meterというアプリがプリインストールされており、マウスカーソルで指した部分の色を16進数等で表示してくれます。この2つを組み合わせることで同じ色を作り出すことができます。

Raspberry Pi 3's OS for server use

raspberry pi 3でwebサーバーとファイルサーバーを建てようと思っており、サーバーと言えばCentOSというネットの情報とCentOS 7になって少し仕様が変わったらしいけど新しく始めるなら新しいものからという自分の信条よりラズパイにCentOS 7を入れてみました。

入れたはいいもののwifiの設定をするにはgitで関連するレポジトリをクローンで持ってくる必要があり、gitの導入にはyumコマンドを使う必要があるのにデフォルトではyumを使うとエラーが出るという壁に当たりました。CentOS 7@ras-piでyumアップデートをするとエラーが出るという症状はどうやら他の方も出ているようです。

参考1 usmysa.hatenablog.com

参考URLの方では解決策も提示してくれているのですが、自分の環境ではyumのエラーは解決しませんでした。試行錯誤しつつ数日経った後、あるネット記事にたどり着きました。

参考2 d.hatena.ne.jp

タイトルと自分が今まで調べた情報より「CentOSおすすめ記事か」などと思い読み進めてみるとどうも様子がちがうようで、世界的に見ればサーバーOS@Linuxとして覇権を握ったのはubuntuのようです。CentOSのシェアが下がったというよりはubuntuの人気が上がったのかなと思います。

参考3 srad.jp

こんな記事もあるので単純に参考2の記事を信頼するのも考えものですが、しかし流行っているものが今後も使われるというのは確かに一理あるとも思われるのでサーバーOSとしてのubuntuの立ち位置はこのまま続くのではないかと自分で判断しました。

というわけでCentOSのインストールはやめ、ubuntu MATEをラズパイにインストールしました。

ubuntu MATE(マテと読むみたいです。スペイン語らしいですね。自分はずっとメイトとよんでいました。)はGNOME 2からフォークされたデスクトップ環境MATEを用いたubuntuでラズパイ用のOSもあります。純粋なサーバーOSではないですが個人が趣味で建てるサーバーなのでインストールと設定の簡便さを優先しました。後ほどデスクトップ環境をアンインストールしてしまえばいいと思ったのもあります。

インストールの手順については色々なブログ等で紹介されているので割愛しますが、インストールしてからの驚きがすごいですね。

まず、設定がGUIなので楽ですね(デスクトップOSなので当たり前ですが)。設定が終わって有線LANを外すとそれだけでwifiが使えるようになってました(初期設定もwifiだけでいけたかもしれないです。)文章で書くとそこまででもないかもしれないですが、wifiを使えるようにするためだけに数日本気で悩んだ自分としてはこれだけでも感動モノでした。

さらに、CentOSではデフォルトでnanoエディタが入っておらず、今まで使ったことのなかったvimエディタで様々な設定をするしかありませんでした(vim自体は高機能なエディタですし、結果として使えるようにすることは損ではなかったのですが)。しかもCentOSのviはvim-tinyとかよばれるもので設定も最小限のものしかなく、yumが使えずvim-enhancedがインストールできなかった自分には辛いものがありました。

一方でubuntu MATEではデフォルトはnanoを使うことが推奨されているようでvim系はvim-tinyがインストールされていたのですが、apt-getでvimをインストールしてhello worldプログラムをC言語で書いてみるとすでにシンタックスハイライトがONになってるじゃないですか!CentOSでもvimをインストールできたらもとからシンタックスハイライトが使えるようになっていたのかもしれないですけど、インストールする段階にまでたどり着けなかったので…

さすがubuntu系は様々なところで至れりつくせりだなーとしみじみ思いました。

正直インストールしたてであまりいじってないのでこのぐらいしか書くことがないのですが、この感動をなにか文として残しておきたかったので書いてみました。思った以上に長文になってしまいました。それでは。

limitlessledその4

limitlessledについての記事は4つ目となります。またしてもlimitlessledの操作をGUIアプリから行おうといういつもどおりの記事です。

前回、前々回もPyQtとledcontrollerを用いてGUIアプリを作成したのですが、コードの読みにくさや冗長な部分があったり、車輪の再発明をしており最適なコードとは言えないものでした。それらを今の段階において改良したものが下記のコードになります。

簡単に前回のコードとの違いを列挙すると、

  • オブジェクト指向プログラミングに則ってGUIのパーツ毎にクラスを定義し、MainWindowクラスに多くのコードを持たせない。
  • タイマー機能をthreadingライブラリのthreadよりサブスレッドを生成しfor文とtime.sleep()関数によって実装していたところをPyQt.QTimerによって実装した。

またデザイン面では

  • タイマーの残り時間をプログレスバーで表記していたところを数字での表記に変更した。

ことが挙げられます。

コードの違いに関しては2つとも保守性の向上が期待できると考えています。 デザイン面の変更はプログレスバーのパーセント表記のためにわざわざ残り時間を選択された時間で割ってやる手間を省きたかったからです。

大きな変更はこの3つぐらいですかね。以下にコードを載せます。

# -*- coding: utf-8 -*-
"""
Created on Sun Mar 26 21:54:31 2017

@author: ujair
"""

import sys
import PyQt4.QtGui as gui
import PyQt4.QtCore as core
import ledcontroller as led
import time as TIME

IP = '192.168.xx.xxx'
LED = led.LedController(IP, group_1='white', group_2='white', group_3='white', group_4='white')


class UI(gui.QMainWindow):
    def __init__(self):
        super().__init__()
    
    def initUI(self):
        #==============================
        # begin menu bar
        #==============================
        exitGUI = gui.QApplication.style().standardIcon(gui.QStyle.SP_TitleBarCloseButton)
        exitAction = gui.QAction(exitGUI, 'Quit LimitlessLED', self)
        exitAction.setShortcut('Ctrl+Q')
        exitAction.setStatusTip('Exit application')
        exitAction.triggered.connect(gui.qApp.quit)
        
        menubar = self.menuBar()
        fileMenu = menubar.addMenu('LimitlessLED')
        fileMenu.addAction(exitAction)
        menubar.setNativeMenuBar(False)
        #==============================
        # end menu bar
        #==============================
        
        
        g1 = group_box1()
        g2 = group_box2()
        
        #==============================
        # begin HBOX1
        #==============================
        on = gui.QPushButton('ON', parent = self)
        on.clicked.connect(LED.on)
        off = gui.QPushButton('OFF', parent = self)
        off.clicked.connect(LED.off)

        HBOX1 = gui.QHBoxLayout()
        HBOX1.addStretch(1)
        HBOX1.addWidget(on)
        HBOX1.addWidget(off)
        #==============================
        # end HBOX1
        #==============================
        
        VBOX = gui.QVBoxLayout()
        VBOX.addWidget(g1)
        VBOX.addWidget(g2)
        VBOX.addLayout(HBOX1)
        
        widget = gui.QWidget()
        widget.setLayout(VBOX)
        
        self.setCentralWidget(widget)
        
        self.setGeometry(0, 0, 300, 300)
        self.show()

class time:
    def __init__(self, sec = 0):
        self.sec = sec
        self.set_sec(sec = self.sec)
    
    def get(self):
        return (self.h, self.m, self.s)
        
    def decrement(self):
        self.sec -= 1
        self.set_sec(sec = self.sec)
    
    def set_sec(self, sec = 0):
        self.sec = sec
        self._h(self.sec)
        self._m(self.sec)
        self._s(self.sec)
    
    def _h(self, sec):
        self.h = int(sec/3600)
    def _m(self, sec):
        self.m = int((sec%3600)/60)
    def _s(self, sec):
        self.s = int(sec%60)

class group_box1(gui.QGroupBox):
    def __init__(self):
        super().__init__('Timer')
        
        self.cancel = False
        self.countdown = 0
        self.progress = 0
        self.time = time()
        self.flag = False

        #==============================
        #  begin hbox1
        #==============================
        self.display = gui.QLabel("{0:01d}:{0:02d}:{0:02d}".format(0, 0, 0), parent = self)
        self.display.setFont(gui.QFont("Menlo", 80))
        self.display.setAlignment(core.Qt.AlignRight)

                
        hbox1 = gui.QHBoxLayout()
        hbox1.addWidget(self.display)       
        #==============================
        #  end hbox1
        #==============================


        #==============================
        #  begin hbox2
        #==============================
        times = gui.QComboBox(parent = self)
        times_text = ['30', '60', '90', '120']
        times.addItems(times_text)
        times.activated[str].connect(self._times_activate)
        
        cancel = gui.QPushButton('cancel', parent = self)
        cancel.clicked.connect(self._stop)
        
        hbox2 = gui.QHBoxLayout()       
        hbox2.addWidget(times)
        hbox2.addStretch(1)
        hbox2.addWidget(cancel)
        #==============================
        #  end hbox2
        #==============================
        
        vbox1 = gui.QVBoxLayout()
        vbox1.addLayout(hbox1)
        vbox1.addLayout(hbox2)
        
        self.setLayout(vbox1)
        
    def _times_activate(self, text):
        print(TIME.ctime())
        minutes = int(text)
        self.time.set_sec(sec = minutes*60)
        self.display.setText("%01d:%02d:%02d" % self.time.get())
        self.countdown = minutes*60
        
        self.flag = True
        
        self.timer = core.QTimer()
        self.timer.setInterval(1000)
        self.timer.timeout.connect(self._countdown_time)
        self.timer.start()
    
    def _countdown_time(self):
        self.countdown -= 1
        self.time.decrement()
        self.display.setText("%01d:%02d:%02d" % self.time.get())
        
        if(self.countdown <= 0 and self.flag == True):
            LED.off()
            self._stop()

    
    def _stop(self):
        self.timer.stop()
        self.countdown = 0
        self.time.set_sec(sec = 0)
        self.display.setText("%01d:%02d:%02d" % self.time.get())
        self.flag = False

class group_box2(gui.QGroupBox):
    def __init__(self):
        super().__init__('Cool and Warm')
        
        #==============================
        #  begin hbox1
        #==============================
        warm = gui.QPushButton('Warm')
        warm.clicked.connect(LED.warmer)
        cool = gui.QPushButton('Cool')
        cool.clicked.connect(LED.cooler)

        
        hbox1 = gui.QHBoxLayout()
        hbox1.addStretch(stretch = 1)
        hbox1.addWidget(warm)
        hbox1.addStretch(stretch = 1)
        hbox1.addWidget(cool)
        hbox1.addStretch(stretch = 1)
        #==============================
        #  end hbox1
        #==============================

        self.setLayout(hbox1)
        
def main():
    app = gui.QApplication(sys.argv)
    ui = UI()
    ui.initUI()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

前回も書いたかもしれませんが、limitlessledのデュアルホワイトモデルを購入したためLEDの指定方法として

group_1 = 'white'

というような書き方をしています。

実際に起動すると以下のような画面になります。

f:id:jinpei0908:20170326231711p:plain

まだまだ未熟ですが一番最初につくったときからはだいぶ進化していると自分では思っています。 よい実装が思いついたらまた改良していきたいと思います。

それではこのへんで。