Python備忘録:リスト化されたディクショナリーの値でソートをする場合の件
何かタイトルがわけ分からん感じかもしれないけどですね、要するに
data = [{'id':'50','data':'AAAA'}, {'id':'7','data':'BBBBB'}, {'id':'256','data':'CCCCCC'}]
というリストになったデータが有ったとして、idでソートをかけるために
data.sort(key=lambda x:x['id'])
とやるとですね、idは文字列扱いなので当然結果は
[{'data': 'CCCCCC', 'id': '256'}, {'data': 'AAAA', 'id': '50'}, {'data': 'BBBBB', 'id': '7'}]
となるわけです。idを数値としてみなしてソートかけたい場合は
data.sort(key=lambda x:int(x['id']))
ということを忘れないようにしたいですね!(以下が修正後の実行結果)
[{'data': 'BBBBB', 'id': '7'}, {'data': 'AAAA', 'id': '50'}, {'data': 'CCCCCC', 'id': '256'}]
Raspberry Piを使ってtorrentダウンロード機(torrent box)を作る
まあ、ここのページのとおりやればいいのですが。
Raspberry Pi Torrent, Samba and DLNA with 3+ hard drives
さて、このままでは色々不都合が有ったり、良く分からなかったりすることがありますので、まずはいくつか説明を。
- Raspberry Pi側につなぐストレージとtorrentでダウンロードするファイルサイズ
もし、torrentで4GB以上のファイルをダウンロードする場合、Raspberry Piにつながるストレージ(USB HDDやUSBメモリ)がFAT32になっていると、ファイルがでかすぎてダウンロードできない(File too large)ということがあります。
そのため、ストレージをNTFS等にしておくのがいいかもしれません。
step1:ストレージをWindows7以降のPCで再フォーマット
step2:Raspberry Pi側でNTFSを使えるようにする。
sudo apt-get install ntfs-3g
step3:/etc/fstabを編集する
sudo nano /etc/fstab
で、fstabの最下行に追加します。なお、ストレージが/dev/sda1の場合です。
/dev/sda1 /media ntfs auto,users,umask=000 0 0
後はリブートするなりして、ストレージをUSBに接続してください。
- "rpc-whitelist"設定は忘れないで!
/etc/transmission-daemon/settings.jsonはtorrentのデーモン(transmission-daemon)の管理等の設定ですが、この中にweb管理画面の設定も含まれていますので、特にrpc-whitelistの設定は忘れると、他のPCから管理画面が触れないというオチになりますので、十分気をつけましょう。
さっきのリンクにも有りましたとおり、
"rpc-username": "(Web管理画面のIDを自由に設定)", "rpc-password": "(Web管理画面のパスワードを自由に設定)", "rpc-whitelist": "192.168.0.*", //この様にアクセスできるIPアドレス範囲を設定
の設定項目の変更と
sudo service transmission-daemon reload
は忘れないでください。
こちらからは以上です!
ArduinoとPCのシリアル通信でデジタル出力を制御する
ArduinoのD2~D9の8つを使って、デジタル出力をします。
出力パターンが決められていたり、即時性がそれほど求められない場合はもっと違う手法が有るのですが、出力に数ミリ秒の分解能が必要だったりすることがある場合に使えるのではないかと思います。
ソースは汚いですが、まずArduinoのスケッチから。MsTimer2をインストールしてください。
#include <MsTimer2.h> volatile byte outdata = B00000000; volatile unsigned int count = 0; volatile boolean dataoutput = false; //デジタル出力中 volatile int ptr = 0; //PCからの電文解析:0は0x40待ち,nはnByte目読み中 volatile boolean nowstop = true; //最初の電文待ちかどうか volatile int TXRXPacketDelta = 0; //電文バッファーがどれだけあるか volatile int bufcont = 0; //電文バッファーのコントロール用パラメーター void samplingOUT(){ byte buf1,buf2; if(dataoutput){ count --; buf1 = (outdata & B00111111)<<2; //PORTD; buf2 = (outdata & B11000000)>>6; //PORTB }else{ buf1 = B00000000; buf2 = B00000000; } PORTD = (PORTD & B00000011) | (buf1 & B11111100); PORTB = (PORTB & B11111100) | (buf2 & B00000011); if(count == 0){ dataoutput = false; } } void setup(){ for(int i=2;i<=9;i++){ pinMode(i,OUTPUT); digitalWrite(i,LOW); } Serial.begin(19200); //Arduinoのシリアルはすぐには初期化できないみたいなので… delay(5000); //分解能は10ミリ秒(10ミリ秒以下のパルスは出せない) MsTimer2::set(10,samplingOUT); MsTimer2::start(); } void loop(){ byte sdata; int incoming = Serial.available(); if(dataoutput == false && incoming >0){ sdata = Serial.read(); if(denbun_parse(sdata) == -1){ bufcont = 1; } } switch(bufcont){ case 1: case 3: if(TXRXPacketDelta >=10){ bufcont = 2; }else{ Serial.write((byte)incoming); TXRXPacketDelta ++; } break; case 2: if(TXRXPacketDelta <=5){ bufcont = 3; } break; default: break; } } int denbun_parse(byte sd){ int ret=0; switch(ptr){ case 0: if(sd == 0x40){ ptr = 1; } return 0; case 1: count = ((unsigned int)(sd))*256; ptr = 2; return 0; case 2: count = count + (unsigned int)sd; ptr = 3; return 0; case 3: outdata = sd; ptr = 4; return 0; case 4: if(sd == 0x80 && count != 0){ if(nowstop == true){ nowstop = false; ret = -1; }else{ dataoutput = true; ret = 1; TXRXPacketDelta --; } } ptr = 0; return ret; } }
PC側からArduinoのシリアルポートへは、以下のような電文のシーケンスが必要になります。
(1)PC側が準備できたら 0x40 0x00 0x00 0x00 0x80の5バイトをシリアルに送信する(実は頭の0x40と0x80以外は何でもいい)。
(2)PC側はシリアルポートから1バイトの電文を受けるたびに、今後出力したい順番通りに以下の電文を出す。
0x40(固定) (2バイトで時間を表す) (ポートの出力パターンを1バイトで) 0x80(固定)
時間はビッグエンディアンで、実際に出したい状態の時間の10ミリ秒で割った数です。
また、ポートのパターンは下位ビットがD2→最上位ビットがD9になります。
(例1) 100ミリ秒間、全ポート出力 → 0x40 0x00 0x0A 0xFF 0x80
(例2) 1分間(60000ミリ秒=6000×10ミリ秒)、D2,D4,D6,D8ポートのみON → 0x40 0x17 0x70 0x55 0x80
ただし、10分以上連続したパルス(要するに時間のところが0xFF 0xFF … 655350ミリ秒)を越す場合は電文を分ける必要があります。
テストしたPC側のPythonのソースです。
Windows7環境下でserialが必要になります。("COM5"は環境に応じて変更してください)
ArduinoのD2出力にLEDを接続すると、1秒間ごとにON/OFFを繰り返し、D3は2秒毎、D4は4秒ごと…となります。
import serial from time import sleep from struct import pack,unpack s = serial.Serial("COM5",baudrate=19200,parity='E',timeout=0) count = 0; sleep(5) s.flushInput() s.flushOutput() sleep(5) s.write(pack('5B',0x40,0x00,0x00,0x00,0x80)) while True: r = s.inWaiting() if r != 0: p = s.read() m = count % 256 head = pack('5B',0x40,0x00,0x64,m,0x80) s.write(head) print "Pulse Output Pattun %d Rest Buffer(Arduino) %d Incoming Buffer(Arduino to PC) %d" % (m,ord(p),r) count = count + 1
SAKURA BOARDを手に入れました
ルネサスのMPU、RX63Nを使ったマイコンボード、SAKURA BOARDをとある人から譲り受けました。
ここにもあるとおり、Arduinoのスケッチの概念やシールドの互換がありそうです。
http://tool-cloud.renesas.com/Renesas/ref/gr_reference_j.html
パッケージです。日本を意識しています。(Arduinoはもっとイタリアを意識して欲しかったな…留めてあるシールくらいだよね…)
Arduino互換のシールドが使えそうですが、Arduino UNOにあるIOREF,ResetピンはSAKURA BOARDにはありません。また、Arduino MEGA程ではありませんが、別途IOポートをつなげられそうです。
Ethernet(RJ-45端子)は標準で、USB端子はミニBタイプ(←若干注意)です。
裏側にはMicroSDカード用のソケットもあります。
茶色いボタン(SW1)はリセットスイッチですが、PCにストレージとしてみなす為に必要なボタンになります。
MPUはArduino UNOがATmega328(16MHz)ですが、SAKURA BOARDはRX63N(96MHz)と高速です。
横から見ると分かるのですが、RJ-45端子の高さが有るので、シールドによってはRJ-45に干渉するかもしれませんね。
これから色々いじってみますが、EthernetやMicroSDを使って面白そうなことができそうな感じがします。
Google Driveスプレッドシートの特定のシートの最初のカラム以外を消す(3)
- 確認と使えるようにするには
このスクリプトがマトモに動くかどうかは画面の以下のところにある「実行」ボタンを押してください。
エラーが出ない場合は、スプレッドシート自体を見に行ってみてください。
こんな(↓)感じになっているはずです。
マトモに動いていると思うので、あとは特定のURLにアクセスすると勝手に消してくれるようにしましょう。
まずは、「ファイル」→「バージョン管理」を選んでください。試験運用中ですがキニシナイ!
すると以下のような画面が出ますので、バージョン名を数字で入力してください。
OKボタンを押すと以下のようになり、左側の「バージョン」の番号を覚えておいてください。最初は「1」になるかと思います。
OKを押して、次は「公開」→「ウエブアプリケーションとして導入」を選択してください。
以下の画面が出たら、先程のバージョン名とアプリケーションの実行する権限を選択して(通常なら、下の画面のようだと思います)導入ボタンを押してください。
しばらくすると非常に重要な以下の画面が出ます。
この「現在のウエブアプリケーションのURL」以下にあるhttpsから始まる行をコピーしてください。
以降、このコピーしたURLをアクセスするたび、スプレッドシートがクリアされます。
アドレスバーにそのまま入れても良いんですが、コマンドラインとかで
/usr/bin/chromium-browser https://script.google.com/macros/s/(ほにゃらら)
みたいなのを実行させても良いのではないかと思います。
追伸
正直超誰得なんだろうね、この記事…。
Google Driveスプレッドシートの特定のシートの最初のカラム以外を消す(2)
(1)からの続き
- スクリプトを書くよ
スクリプトの仕様とかは英語で書かれています。
https://developers.google.com/apps-script/overview
Javascriptチックなので、腕に覚えのある人はさほど難しくないと思います。
さて、先程のエディタの画面に以下を入力していきます。
function myFunction() { //SheetのIDには後ほど説明するスプレッドシートのKeyを入れる。 //このスプレッドシートのタブ「data」にアクセスする場合 var sheetid = SpreadsheetApp.openById("SheetのID").getSheetByName("data"); // 行(縦方向)の最終行番号を取得 lastrow = sheetid.getLastRow(); //列(横方向)の最終番号を取得 lastcor = sheetid.getLastColumn(); //2行目から最後までクリアします。 sheetid.getRange(2,1,lastrow,lastcor).clear(); } // doGetという関数がアクセス時に呼ばれます function doGet(){ myFunction(); return UiApp.createApplication(); }
で、このスクリプトの"SheetのID"ってのは何かというとですね、スプレットシート自体のURLを見ていただくと以下のような感じになっていると思います。
https://docs.google.com/spreadsheet/ccc?key=
のあとの文字で、「#」より前の文字が、そのSheetのIDとなります。この文字をコピペしておいてください。
なお、入力中は以下のようにVisual Studioで言うところのIntellisense的なことが出ますので安心ですね!
スクリプトを入力が済んだら保存しましょう。
スクリプト自体のファイル名と、複数のスクリプトをまとめることができるプロジェクトに名前をつけましょう。
(スクリプトの名称変更)
(プロジェクト名を付ける)
「ファイル」の「名前を付けて保存」で以下の画面が出ますので、プロジェクト名(Google Driveに表示される名称)を入力して、「OK」を押しておいてください。
後でGoogle Driveのトップ画面を見るとこんな感じになるはずです。
(3)へ続く
Google Driveスプレッドシートの特定のシートの最初のカラム以外を消す(1)
GoogleDrive使ってますか?
私は市場が開いている日は、日経先物の素データをスプレッドシートにぶち込んで、出先とかでも色々いじって楽しんでいるのですが。
そんなわけで、スプレッドシートを毎日データ更新するのですが、特定のシートを消すけど、最初のカラム(データの項目名)を残して全部消すことが要求されます。
みんな、そんな事で困ってるよね?(多分困ってない)
ということで、GoogleDrive内のコンテンツをいじる為にある、Google Apps Scriptの使い方とかのメモを。
- まずはデータを。
ブラウザーでGoogleDriveを開いたあと、Google Drive内にこんな(↑)タイトルのスプレッドシートが有るとします。
中身はこんな感じ。
先程の画面の「作成」ボタンを押すと作成できるコンテンツの一覧が出てきますが、マニア用なので(意味不明)、もっと見るに移行すると、「スクリプト」というのが出てきますので、ここを選択してください(下の画面)。
その後以下の画面が出ますので、左上の「空のプロジェクト」を選んで下さい
するとエディタな感じのするページが出てきます。
ここにスクリプトを書いていきます。
(2)へ続く