Beyond The Limit

はじまりは2001年

もうすぐ一年が経ちます

転職してからもうすぐ一年が経ちます。気がついたら早いもので、この一年で公私ともに色々とありました。

転職して一年が経つということは、セールスエンジニアのキャリアも一年が経つということになります。 半年ぐらい前にはてなアドベントカレンダーにて、仕事のこととか書いてました。

sharatani.hatenablog.com

セールスエンジニアという肩書きで一年間ほど仕事をしてきたのですが、面白い仕事だな〜って一言に尽きます。 一生懸命やっているので、しんどいこともあれば、楽しいこともあるのが仕事なのですが、これまでの社会人としての人生を振り返っても面白い仕事です。

一年前を振り返ると、だいぶ成長した感はあるのですが、まだまだいけるしまだまだやれるし、まだまだやりたいことはたくさんあるので頑張ります。 弊社のCTOが「自分に限界を定めると、それが仕事の限界になる」というようなことを言っていて、厳しくなるとその言葉をよく思い出したりしています。

やりたいこと、知りたいこと、気になる技術はまだまだたくさんあるので頑張る!

MackerelでWindowsイベントログ監視とプロセス監視をする

ちょっと触ってちょっと検証したため、メモしておきます。

MackerelはWindowsでも利用可能ですが、公式のcheckプラグインWindowsに対応していないため、個別に用意する必要があります。

※プロセス監視のcheck-procsは公式に用意してあるのですが、自分でビルドする必要があります。

環境

Mac OSXを利用しています、gitやhomebrewなどは予め環境が出来ているという状況です。

Go環境の整備

Goの環境整備にあたっては、弊社のSongmuさんの記事を利用させてもらいました。

www.songmu.jp

check-procsのビルド

予め"$HOME/repos"というディレクトリを作っておきました。

git clone https://github.com/mackerelio/go-check-plugins.git

git cloneしてローカル環境にデータを持ってきます。

GOOS=windows GOARCH=386 go build -o check_procs_windows.exe

でビルドすると、こんなエラーが出ました。

check_procs.go:9:2: cannot find package "github.com/jessevdk/go-flags" in any of:
    /usr/local/Cellar/go/1.6/libexec/src/github.com/jessevdk/go-flags (from $GOROOT)
    /Users/sharatani/dev/src/github.com/jessevdk/go-flags (from $GOPATH)
check_procs.go:10:2: cannot find package "github.com/mackerelio/checkers" in any of:
    /usr/local/Cellar/go/1.6/libexec/src/github.com/mackerelio/checkers (from $GOROOT)
    /Users/sharatani/dev/src/github.com/mackerelio/checkers (from $GOPATH)

パッケージが見つからないと出ているので、以下のコマンドを実行します。

go get github.com/jessevdk/go-flags
go get github.com/mackerelio/checkers

その後で改めて以下のコマンドでビルドをします。

GOOS=windows GOARCH=386 go build -o check_procs_windows.exe

すると、check_procs_windows.exeが出来ています。

検証

AWSのWindowsServer2012R2で試してみました。

  • タスクマネージャー起動させる
  • コマンドプロンプトで"check_procs_windows.exe --pattern Task"実行
    • "Procs OK: Found 1 matching processes; cmd /Task/"が表示されたのでOK
  • タスクマネージャーを終了させて、再度コマンド実行して確認
    • "Procs CRITICAL: Found 0 matching processes; cmd /Task/"が表示されたのでOK

mackerel-agent.confへ記述するには、こんな感じです。

[plugin.checks.taskmanager-procs]
command = "C:\\Users\\Administrator\\Downloads\\check_procs_windows.exe --pattern Task"

confを変更して有効化するには、サービスからmackerel-agentを再起動させる必要があります。

Windowsのイベントログ監視

イベントログを監視するにはいくつか方法があるのですが、試した結果、パワーシェルを使うよりもexeを使った方が楽でした。

一旦こちらからexeプログラムをダウンロードします。

check_winevent - NRPE check plugin for Windows eventlogs | itefix.net

単体でコマンドプロンプトから実行したら、こんな感じでした。

C:\> check_winevent.exe --log application --type error

EVENT OK - 2 events|events=2;;;

これはアプリケーションログに対して、タイプがエラーになっているものが2件見つかったため、2と表示されています。 2と言ってもログの確認範囲(いつからいつまでなのか)が分からなかったので、いくつか試したところ・・・・

試しにコマンドをちょっと変えて実行してみました。

C:\> check_winevent\\check_winevent.exe --log application --type error --critical 0

EVENT CRITICAL - 2 events|events=2;;0;

0以上の場合はCRITICALにするオプションを付与したところ、CRITICALが返ってきています。

--verboseオプションを付与して、出力を詳細に出してみました。

C:> check_winevent.exe --log application --type error --verbose

Event log(s): application
Event code(s): all
Event type(s): error
Event sources: all
Time window: 3600 seconds, timestamp: 20160517043648.000000+000
Eventlog application - 2 selected events
Total number of events selected: 2

EVENT OK - 2 events|events=2;;;

これを見ると、Time windowという項目が有り、3600秒=60分が検出の対象になっているようです。 --windowオプションで秒数を変更出来るようなので、60秒にして実行した見たところ、今度はCRITICALではなくOK表示でした。

C:> check_winevent.exe --log application --type error --critical 0 --window 60

EVENT OK - 0 events|events=0;;0;

他にもいくつかオプションはあるようなのですが、ちゃんと動いていそうなので、細かい所はまた後で。

mackerel-agent.confにはこのように記述します、記述後はサービスからmackerel-agentを再起動させて反映します。

[plugin.checks.windowsApp-exe]

command = "C:\\Users\\Administrator\\Downloads\\check_winevent\\check_winevent.exe --log application --type error --critical 0"

IDCFクラウドMeetup!in Osaka vol.1に参加してきました

昨日はこちらのイベントに参加してきました。

idcfugosaka.doorkeeper.jp

今回の会場はファーストサーバーさんの会議室をお借りしていて、会議室は満席の状態。 大阪では初開催だったのですが、とにかく人が多くて、利用者からの愛され感が伝わる会場でした。

さいとうさん(IDCF-UG代表)の発表

  • 会場にいる人達へのアンケート・・・「使っている人手を挙げて下さい」
  • 単純比較はできないが、IDCFクラウドは他クラウドと比較して起動速度が速い
    • その中でもradianリージョンが一番早い、東日本リージョンはradianがおすすめ
  • オールフラッシュ本当に速いのか?
    • さいとうさんがRead速度を検証した結果、目を疑うレベルで速い!
      • 元々速かったけど、より速くなった
  • クーポンフル活用案
    • 3千円クーポンで500円サーバーを一時的に利用して、検証・ハッカソンなどをしてみる
  • ユーザーグループを立ち上げた理由
    • ユーザー目線で本音のフィードバックをしたいというのが主な理由
  • コミュニティテンプレートのハッカソンを企画中!

IDCF藤城さんの発表

  • 趣味活動で72Core/128GBmemのマシンを利用して、自宅でベンチマークやってる
  • 「実はIDCFって○○なんです」×7!
    • 実はIDCFクラウドが300円くらいでも十分使えます

      • サーバーS1+ボリューム4GBだと280円
        • ブラウザ上でKVMコンソールが使えるから、何かあった時には色々と便利
        • コンソールの利用時にはVMware Toolsのインストールがオススメ
    • 実は無料でロードバランサーがあり、それなりに使えます

      • Active-Standbyの冗長構成、ヘルスチェックもある、パーシステンスもある、レポート情報も見られる
      • 仮想ルーターはMackerelで監視可能
    • 実は標準でDDoS対策がついてます

      • 利用者側は何もしなくてもOK!
      • レポーティング・コンサルティング・チューニングの有償プランもあり
    • 実は今後新しいゾーンはすべてオールフラッシュです

      • I/Oが超高速、IOPSも安定、値段も据え置き
        • でも従来のストレージも結構速い
    • 実はサーバーを起動した状態でスペックアップができます

      • あんまり知られていないが、実は目玉機能の「ダイナミックスケール」
        • いくつか制限はあるので、詳細はFAQやテックブログを
    • 実はメタデータサーバーがあります

    • 実は「ほぼ毎週リリースをしています」

      • Mackerelの毎週リリースを意識して対応してくれてる(嬉しい)
      • 機能要望はチケット経由がベスト!

はてなSongmuさんの発表

  • 「Mackerelはこう使え!」
    • IDCFのVM作成からMackerelのインストールを兼ねたデモ、Mackerelの紹介やロードマップ紹介など

IDCFクラウドユーザーグループ大阪は逢坂さん一人なので、メンバーを募集しているそうです。 まだ立ち上げたばかりと言っても、今回だけでたくさんの方が来場されているので次回がとても楽しみですね。

Python学習メモ7

位置引数のタプル化

関数の引数を可変にして仮引数にセットしている。

>>> def print_kahen(*args): *は必要だが、argsじゃなくても良い。慣習的にargsになっている。
...     print ('kahen argument:',args)
...
>>> print_kahen(1,2,3)
kahen argument: (1, 2, 3)
>>>
>>> print_kahen()  引数が何もない場合は何も無い
kahen argument: ()
>>>
>>> def print_kahen2(need1,need2,*args):   引数1と引数2、その他は全てotherに入る
...     print ('need1=',need1)
...     print ('need2=',need2)
...     print ('other=',*args)
...
>>>
>>> print_kahen2(1,2,3)


need1= 1
need2= 2
other= 3
>>> print_kahen2(1,2,3,45)
need1= 1
need2= 2
other= 3 45
>>> print_kahen2('App','Disk',3,'Memory')
need1= App
need2= Disk
other= 3 Memory
>>>

docstring

関数内にドキュメントを残す場合、help(関数名)で関数の中に残されたドキュメントを整形して表示してくれる

関数の定義

>>> def add_args(args1,args2):  引数1と引数2を合算する関数
...     print (args1 + args2)
...
>>> add_args(100,29)
129
>>> def run_some2(func,args1,args2):   run_some2関数は引数を3つ取る
...     func(args1,args2)   func=引数1つめの関数を実行する、funcの引数はrun_some2の引数2と引数3を指す
>>> def run_some2(func,arg1,arg2):
...     func(arg1,arg2)
...
>>> run_some2(add_args,50,80)  run_some2関数にadd_args関数、50、80を引数として渡した
130 add_args関数が実行され、50+80=130が結果として帰ってきた
>>>

Python学習メモ6

内包表記

  • リスト内包表記

[expression for item in iterables] コンパクトに構文を作成できる

>>> num_list = []
>>> for num in range(1,6):
...     num_list.append(num)
...     (forの処理の終わりは何も入力せずにEnterを押す)
>>> num_list
[1, 2, 3, 4, 5]
>>>
    上も下も同じ事を実施したということ
>>> num_list = [num for num in range(1,6)]
>>> num_list
[1, 2, 3, 4, 5]
>>>
  • 辞書内包表記

{key_item:value_item for item in iterable}

辞書でも同じようにできる

>>> let_count = {letter:words.count(letter) for letter in words}
>>> let_count
{'l': 1, 't': 2, 's': 1, 'r': 1, 'e': 2}
>>>
  • 集合内包表記

{item for item in iterable}

  • ジェネレータ内包表記

タプル()には内包表記がない、リスト内包表記の[]を()に変えても正常動作するが、これはジェネレータ内包表記となる

ジェネレータは一度しか実行出来ない、一度作ると値をイテレータに渡してしまうので作った物を再利用できない。

>>> num_list = (num for num in range(1,6))  こんな感じでジェネレータ内包表記を作る
>>> for numb in num_list : こんな感じで取り出す
...     print (numb)
...
1
2
3
4
5
>>>     print (numb)
  File "<stdin>", line 1
    print (numb)
    ^
IndentationError: unexpected indent
>>>

関数

  • 最初にdef、次に関数名を各、関数に対する入力引数をかっこに囲んで各、最後にコロンを書く
>>> def com(color):
...     if color == 'red':
...             return 'color is red'
...     elif color == 'blue':
...             return 'color is blue'
...     elif color == 'green':
...             return 'color is greeeeeen'
...     else:
...             return 'other'
...
>>>
>>> com('red')
'color is red'
>>> com('blue')
'color is blue'
>>> com('greeen')
'other'
>>> com('green')
'color is greeeeeen'
>>>
>>> com2 = com('white')
>>> com2
'other'
>>> com3 = com('red')
>>> com3
'color is red'
>>>

位置引数

  • 先頭から順番に対応する位置の仮引数にコピーされる位置引数、関数の引数が何をどの順番にしているのかを覚えておかないといけない
>>> def menu(a,b,c):    位置引数から辞書を作って返す
...     return {'drink':a,'food':b,'etc':c} aの引数はdrinkに対応する、bの引数ははfoodに対応する、cの引数はetcに対応する
...
>>> menu('coffee','cake','cherry')
{'food': 'cake', 'etc': 'cherry', 'drink': 'coffee'}    ただし対応しているが、返ってくる順番はバラバラ
>>>

キーワード引数

  • 位置引数で定義した仮引数の名前を指定して実引数を指定する、順番はばらばらでも構わない
>>> menu(c='beer',b='apple',a='niku')
{'food': 'apple', 'etc': 'beer', 'drink': 'niku'}   drink,food,etcにそれぞれ対応している
>>>
>>> menu('beer',c='apple',b='niku')    位置引数と併用する場合、先に位置引数を指定する必要がある
{'food': 'niku', 'etc': 'apple', 'drink': 'beer'}
>>>
>>> menu('beer','apple',c='niku')  cだけ後で指定した場合
{'food': 'apple', 'etc': 'niku', 'drink': 'beer'}
>>> menu('beer',b='apple','niku')  この場合はエラーになる
  File "<stdin>", line 1
SyntaxError: positional argument follows keyword argument
>>>

デフォルト引数値の指定

  • 引数が何も指定されなかった場合など、デフォルト値を設定することができる
>>> def menu(a,b,c='prin'): cに何も設定されなかった場合は'prin'を返す
...     return {'tabemono':a,'nomimono':b,'etc':c}  その場合はetc:printとなる
...
>>>
>>> menu('ebi','ikura')    a,bは指定、cは何もなし
{'nomimono': 'ikura', 'etc': 'prin', 'tabemono': 'ebi'} etc:prinが返ってきた
>>>

Puthon学習メモ5

  • リストは、タプルは()、辞書は{}で作る
  • いずれにしてもを使って値を取り出す、辞書の場合はキーを入れる、それ以外は整数のオフセットを入れる

  • Pythonには複数行コメントはない、複数の場合も頭に#を付ける

辞書を使ったfor文

>>> e2f
{'cat': 'chat', 'walrus': 'morse', 'dog': 'chien'}
>>> for i in e2f:
...     print (i)   キーが返ってくる
...
cat
walrus
dog
>>>
>>> for i in e2f.values() :    values()関数を付けると、キーではなく値が返ってくる
...     print (i)
...
chat
morse
chien
>>>
>>> for i in e2f.items() : items()関数を付けると、キーと値がタプルで返ってくる
...     print (i)
...
('cat', 'chat')
('walrus', 'morse')
('dog', 'chien')
>>>
>>> for i1,i2 in e2f.items() :
...     print ('one is',i1,'two is',i2) i1にkey、i2にvalueを入れた場合


...
one is cat two is chat
one is walrus two is morse
one is dog two is chien

リストの場合はこんな感じ

>>> a
[1, 2, 3]
>>> for i in a :
...     print (i)
...
1
2
3
>>>

今年うまくいったこと・もう少し改善できたはずのこと

Pocketにストックした記事を漁っていたら、2014年末に保存したこんな記事を発見。

今年なにがうまくいき、何が問題だったかをまとめる、2014年の年間レビュー
lifehacking.jp

なんか今年の6月以降が色々とあり過ぎたのだけど、改めて思い返していきたい。

今年うまくいったこと

いくつか本を読めた

エッセンシャル思考、嫌われる勇気、キャズム、その他。

他にも買ったけど読めていない本があるので、これから読んでいきたい。 特にキャズムは勉強になることが多く、今担当しているプロダクトをどう延ばしていくかにも関わっていることなので、本当に良かった。 「すごい!」と思える人が勧める本というのはやっぱり良いものだった。

表彰されて副賞(賞金)をもらった

前職にて、ファミリーデーの企画・実行をしてグループ企業全体の中で表彰された。 開催されたのは2014年なんだけど、その時に知り合った人達とは今でも交流があるし、ほんと良い出来事だった。

転職した

2014年末からずっと動いていたのだけど、最終的には3つの会社から内定をいただいた。 色々と思う所がある転職だったし、入ったところも色んな意味ですごい人しかいない環境なので大変なこともあるけど、良かった。 3月31日に一次通過の案内をもらって、二次面接で京都に行ったのも今では良い思い出。 一日ずれてたらエイプリルフールだったので、ちょっとだけドキドキしてたのも良い思い出。

「迷ったらチャレンジ」ができた

今までもチャレンジの連続だったし、今もチャレンジの連続だけどチャレンジができるということが良かった。 もちろんチャレンジした結果、全てが良いことばかりとはいえないけど、そこから得るものも必ずあるので、チャレンジをするかどうか以前のチャレンジができるということが良かった。ほんとうに。

素晴らしいと思えるプロダクトに出会えた

10年程前に担当した仕事で監視周りの設定を色々といじることがあり、その時に欲しかったものを今誰かに勧める仕事をしている。 プロダクトの詳細自体は転職時に知ったのだけど、素晴らしいものを素晴らしいと素直に言えるのはとても良いことだと思う。 転職面接の時に「絶対に売れる!売れないはずはない!間違いない!」と連呼してたのだけど、今でもそう思っているし、実際にそうなのだから素直に嬉しい。

KaizenさんからApple Watchをいただいた

マーケティングEXPOでKaizen Platformさんへ日々の御礼を兼ねて名刺交換をさせていただいたのだけど、どうやらEXPOの抽選も兼ねていたようで、抽選の結果Apple Watchをいただきました。すごい。気前がいい。 もったいなさ過ぎてまだ会社に置きっ放しなので、早めに有効活用したいと思います。ありがとうございます!

naoyaさんとお話できた

つい昨日の出来事ですが、CodeIQのイベントにてKaizen Platformの伊藤直也さんとお話できました。 自分自身がはてなを知るきっかけになった人でもあり、すごいなーすごいなーと日々思っていたので、(普通に話をしただけだけど)とても良い刺激になった。

今年を振り返るというよりも、なんか自社の良いとこばかりを挙げそうになってしまうから自重。 こう考えると、今年一年を振り返って前半・後半で人生変わったぐらいのインパクトがある。でも変わったのは環境であり、もっと良くするための日々の努力は怠らないようにしたい。

今年もう少し改善できたはずのことは何か?

職種転換があったので、新しいことをもっとキャッチアップしたい

半年の切れ目で職種が変わり、かつ求められるものが(今の自分には)難しいものもいくつかあったので、今まで培ったものにこだわたずに新しいことをキャッチアップしたい。 簡単にはいかないことだけど、やり方・方法を踏まえて地道に着実にやっていきたい。

GTDをもっとやりたいし、整理もしたい

2015年初めにGTDをしっかりやってみようと志したものの、転職活動やら何やらで落ち着かず、結局できず。 2016年と言わず、今からでも遅くないのでちゃんとやっていきたい。 その前にもう一度GTDとは何か、から振り返りたいところ。

もっと本を読めたはず

では、本を読めたはずの時間はどこにいったのか? 時間とは気がつかない間に過ぎていくものなので、もうちょい何とかしたい。 (そう思って自宅で勉強する際にポモドーロタイマーを使ってみたら、思いのほか良かった。)

頭の回転を上げたい

抽象的だけど、物事を広く収集する・整理する・出力するの精度と回数を上げたい。 その為には頭の回転を上げて、サッと切り替えてササッと動けるようにしたい。

計画を立てるのが苦手なのを克服したい

GTDもそうだけど、整理する・計画する・遂行する、これの計画を立てるのが苦手なので上手いことまとめたい。 そういう知識も技術も必要なのかもしれないけど、偏りすぎないように自分の頭で考えて計画を練って、落とし込んで…をGTDを通して練習したい。

来年、どんなアクションをどのタイミングで行うか?

計画を立てるのは苦手と言わず、来年と言わず、早め早めに着手したい。

Python学習メモ4

タプル

タプルはリストと異なりイミュータブルである。 タプルを定義するのは括弧ではなく、カンマ。ただ括弧があれば分かりやすい。 要素が一つでも最後にカンマを入れる必要がある、入れなければただの変数格納になる。

>>> tapuru1 = 'AA', タプル
>>> tapuru1
('AA',)
>>> tapuru2 = ('BB',)  タプル
>>> tapuru2
('BB',)
>>> tapuru3 = 'CC' タプルではない
>>> tapuru3
'CC'
>>> tapuru4 = ('DD')   タプルではない
>>> tapuru4
'DD'
>>>

以下はタプルのアンパックと呼ばれる、タプルを使えば複数の変数を一度に代入できる

>>> tapuru5 = ('EE','FF','GG',)
>>> tapuru5
('EE', 'FF', 'GG')
>>> a,b,c = tapuru5    a,b,cにそれぞれ0,1,2の変数を格納する
>>> a
'EE'
>>> b
'FF'
>>> c
'GG'
>>>

入れ換えも簡単にできる

>>> aaa = '123' ここは変数代入
>>> bbb = '456'    ここも変数代入
>>> aaa,bbb = bbb,aaa  aaaとbbbを交換している
>>> aaa
'456'
>>> bbb
'123'
>>>

tuple(リスト名)を使えばリストからタプルへ変換もできる

辞書

他言語では連想配列やハッシュと呼ばれるもの

In [10]: testdic = { {で始まり
"day1" : "a day",   :で区切り、最後がカンマ
"day2" : "perfect day",
}   }で締める

dict()関数を使えば、2要素のシーケンスを辞書に変換できる

>>> list1 = ['a1','b2','c3','d4']
>>> dict(list1)
{'a': '1', 'c': '3', 'd': '4', 'b': '2'}    変換された、辞書内の順番は決まっていないのでばらばらになる
>>>

辞書のキーを表示させる

>>> dict1 = dict(list1)
>>> dict1
{'a': '1', 'c': '3', 'd': '4', 'b': '2'}
>>>
>>> dict1['a']
'1'
>>> dict1['a'] = 10    キーaの値を変更
>>> dict1['a']
10
>>> dict1
{'a': 10, 'c': '3', 'd': '4', 'b': '2'} aが10に変わっている
>>>

update()で辞書の"結合"ができる

>>> list2 = ['e5','f6'] list2に新しい値を入れておく
>>> dict2 = dict(list2)    dict2にlist2を辞書変換したものを入れる
>>> dict2  辞書変換されている
{'f': '6', 'e': '5'}
>>> dict1  dict1の中身を表示
{'a': 10, 'c': '3', 'd': '4', 'b': '2'}
>>> dict1.update(dict2)    dict1にdict2を追加
>>> dict1  dict2のe5とf6が追加されている、dict2の中身は消えずにそのまま。仮にdict1とdict2のキーが被っていた場合は後からきたもの(dict2)の値で上書きされる
{'a': 10, 'd': '4', 'e': '5', 'f': '6', 'c': '3', 'b': '2'}
>>>

del文でキーを指定するとキーと要素を削除出来る

>>> dict2
{'f': '6', 'e': '5'}
>>> del dict2['f'] ''がないとエラーが出る
>>> dict2  f6の要素が消えている
{'e': '5'}
>>>

[key]を指定すると辞書にキーが追加出来る

>>> dict2
{'e': '5'}
>>> dict2['f'] = 6
>>> dict2  f6が増えた
{'f': 6, 'e': '5'}
>>>

clear()で辞書の中身を全て消去できる

>>> dict2
{'f': 6, 'e': '5'}
>>> dict2.clear()
>>> dict2  消えた
{}
>>>

inで要素の有無を確認できる

>>> dict1
{'a': 10, 'd': '4', 'e': '5', 'f': '6', 'c': '3', 'b': '2'}
>>> 'a' in dict1   キーを指定する
True
>>> '10' in dict1  値は指定しない
False
>>>

辞書から要素を取り出すときに辞書専用のget()関数を使うと色々できる

>>> dict1.get('a')  普通に要素を取り出す
10
>>> dict1.get('10','Not Found')    指定したキーが無い場合は'Not Found'を返す
'Not Found'
>>> dict1.get('10')    オプション(Not Foundのとこ)が無ければNoneになる
>>>

kyes()で全てのキーを返す、values()で全ての値を返す

>>> dict1
{'a': 10, 'd': '4', 'e': '5', 'f': '6', 'c': '3', 'b': '2'}
>>> dict1.keys()
dict_keys(['a', 'd', 'e', 'f', 'c', 'b'])
>>> dict1.values()
dict_values([10, '4', '5', '6', '3', '2'])
>>>

keys()やvalues()で返ってきたものをリスト化する

>>> list(dict1.keys())  list関数の中で呼び出す
['a', 'd', 'e', 'f', 'c', 'b']
>>> list(dict1.keys())[0]  list[0]を取り出した状態
'a'
>>>

items()でkeyとvalueのセットが全て返ってくる

>>> dict1.items()   全て返ってきた
dict_items([('a', 10), ('d', '4'), ('e', '5'), ('f', '6'), ('c', '3'), ('b', '2')])
>>> list(dict1.items())    全て返してlist化した、タプルで返ってくる
[('a', 10), ('d', '4'), ('e', '5'), ('f', '6'), ('c', '3'), ('b', '2')]
>>> list(dict1.items())[0] list化して最初のセットを取り出した状態、タプルで返ってくる
('a', 10)
>>>

辞書の場合も元の辞書が=で書き換えられてしまったら、コピーしたものも書き換わる。 必要に応じてcopy()で元の辞書を書き換えても影響が内容にする。

集合

集合は値を取り出してキーだけを残した辞書のようなもの。

set()で作るか{}で値のみを入れて作る

>>> syuugou1 = set()    空の場合、実際には空の辞書が作られる
>>> syuugou1
set()
>>> syuugou1 = {   値のある集合
... 1,2,3,4,5
... }
>>> syuugou1
{1, 2, 3, 4, 5}
>>>

文字列から集合を作る場合

>>> set('letters')
{'s', 'e', 'r', 'l', 't'}   重複している文字は省かれる
>>>
>>> set({'1':'a','2':'b','3':'c',})    辞書を渡す
{'1', '3', '2'} キーのみ使われる
>>>

&またはintersection()を使うと積集合(両方にある共通の要素)が出力される

>>> a = {1,2}
>>> b = {2,3}
>>> a & b
{2}
>>> a.intersection(b)
{2}
>>>

|またはunion()を使うと和集合(どちらか片方にある要素)が出力される

>>> a | b
{1, 2, 3}
>>> a.union(b)
{1, 2, 3}
>>>

-またはdifference()を使うと差集合(先のものにあって後ろのものにないもの)が出力される

>>> a - b   aには1はあるが、bには1がない
{1}
>>> b -a   bには3はあるが、aには3がない
{3}
>>> a.difference(b)
{1}
>>> b.difference(a)
{3}
>>>

^またはsymmetric_difference()を使うと排他的OR(どちらか片方には含まれているが、両方には含まれていない要素)が出力される

>>> a ^ b
{1, 3}  両方に2が有るので、それ以外が表示される
>>> a.symmetric_difference(b)
{1, 3}
>>> c = {4,5}
>>> a.symmetric_difference(c)
{1, 2, 4, 5}    両方ともで被っているものはないので、全て表示される
>>>

<=またはissubset()を使うと部分集合になっているかどうかをチェックできる

>>> a <= b
False
>>>
>>> d = {1,2}
>>> a <= d  dはaの要素を全て含んでいるのでTrueが返る
True
>>> d = {1,2,3}
>>> d
{1, 2, 3}
>>> a <= d      dはaの要素を全て含んでいるのでTrueが返る
True
>>>

補足

<を使うと真部分集合になっているかどうかをチェックできる

>=を使うと上位集合になっていえるかどうかをチェックできる

>を使うと真上位集合になっているかどうかをチェックする。

セールスエンジニアという役割で半年仕事をしてみて

こんにちは、はてなのMackerelチームでセールスエンジニアをしているid:sharataniです。 本日ははてなデベロッパアドベントカレンダーの一環として記事を書きました、昨日はid:astjさんです。

developer.hatenastaff.com

実ははてなではセールスエンジニアという職種は私しかおらず、この職種での採用も初めてだったそうです。

セールスエンジニアといっても業界によって趣が異なるところもあり、会社によっても呼称が様々だったりするようです。 最近参加している勉強会でもその話題が出てくることもあり、会社によってはエバンジェリスト・セキュリティアーキテクト・システムアーキテクト等の呼称で採用をしているところもあるようです。

私自身もあまり馴染みが無かったこともあり、どんな仕事をしているのか(私の場合となりますが)ご紹介させていただきます。

セールスエンジニアとは

"セールスエンジニアとは"で検索してみたところ、いくつか記事が見つかりました。

セールスエンジニアとは、どんな仕事?|エンジャパンの転職大辞典|エン転職

プリセールス・セールスエンジニアの仕事内容とは。働き方から平均年収、未経験からの就職のコツまで解説! | 職種図鑑 |転職@type

セールスエンジニアの仕事内容 | Find Job !

セールスエンジニア | 大学・学部・資格情報 | Benesse マナビジョン

セールス+エンジニア=セールスエンジニア、なのでセールスのことも理解しつつ、エンジニア的なことも理解をしなければいけません。 エンジニアがそうであるように、セールスと一言で表現しても幅が広く、奥も深いものです。

セールス・エンジニア両方の視点を持った上で仕事をしないといけないのですが、仕事の幅が広い分やること・やらないといけないこと・やった方がいいことは多岐に渡ります。 むしろ"やらなくていいこと"というのはあまり無いと感じています。

具体的にどんなことをしているのか

私が入社したのは半年前になりますが、この半年でこんな仕事をしてきました。

  • セールス
    • お客様訪問
    • お客様先でのハンズオンや説明会の実施
  • マーケティング
    • 競合サービス・ツールの調査や使用感の確認、連携事業者様との協業展開
  • イベント
    • Mackerelミートアップやドリンクアップの実施
    • 実施会場の選定・提供企業様との調整・登壇者様への依頼、その他細かいこと
    • イベント結果のまとめ
  • Mackerelのフィードバック・サポート
    • 弊社のサポート部やMackerelの開発メンバーと協力して対応しています
  • Mackerelヘルプの更新
    • フィードバックや質問の内容から問い合わせ傾向を把握し、ヘルプの更新をします
  • Mackerelの検証作業
    • 新しい機能が出た時やサポート宛に問い合わせをいただく中で検証作業を行います

タイミングによっては1週間のうち毎日どこかに出かけてMackerelの話をすることもありますし、日に2〜3件ほどお客様訪問をする時もあります。 もちろん一つのことに集中して仕事をすることもありますが、足を動かしつつ、手を動かしつつ、頭で考えつつ、色々なものが同時に進行していきます。

どんな仕事でも求められることだとは思いますが、複数のことを並行して処理を進めることやバランス感覚がとても大事です。 そしてセールス・マーケティングを行う上での技術に関する下地も大切なので、日々の勉強を継続することも欠かせません。

こうやって書いてみるといわゆる"何でも屋"的な側面もあるように思いますが、技術に興味がある・技術が好き・ITが好き・色々なことをやってみたいという人にとっては向いている仕事なのかもしれません。 Mackerelの提案・サポート・ヘルプの更新はエンジニア職や技術職の経験が無いと難しいですし、何よりも技術に対する興味がなければ務まりません。 セールスエンジニアという職種の"エンジニア"部分はある程度の技術的な基盤・下地がないと難しい仕事だなと感じた半年でもありました。

セールスエンジニアに必要なもの

セールスエンジニアとはどんな仕事なのか、私の場合は具体的にどんな仕事をしているのかを簡単に書いてみました。 最後にセールスエンジニアに必要なものとして、技術力・提案力・推進力もそうですが、一番は"プロダクトに対する愛"ではないかなと思います。

プロダクトに対する愛というのは人それぞれだと思いますが、かつて運用周りの仕事をしていた際、モニタリング周りで苦労をしていました。 当時苦労したという自分の経験からも「Mackerelはこんなに簡単にインストールが出来て、キレイなグラフが表示されて設定も簡単で日本語のヘルプもあってとても便利に使える、知らない人には知って欲しいし、苦労をしている人には楽になって欲しい。」と思っています。 この過去の経験とMackerelの良さがプロダクトへの愛にもつながっていますし、この仕事をやってみたいという入社への動機にもつながりました。

最後に

いわゆるフィードバック・サポートへの問い合わせというと、要望や質問を書いて送信することが多いと思います。 しかし、この半年を通じてサービスを利用することで従来と比較して楽になった・助かった・良かったということも一つのありがたいフィードバックであり、サービスを提供している人への応援メッセージだということがよく分かりました。

改めて自分自身が利用している他の素晴らしいWEBサービスにも、そのようにサービスの良い点・助かった点などをフィードバックとして送信しようと思うようになりました。

明日は同じMackerelチームのアプリケーションエンジニアでもある、id:stefafafanが担当です。(社内では隣の席です)

Python学習メモ3

文字列の続き、リスト

append()

末尾に要素を追加する。

extend()

リストの結合をする。

+= リスト名でも同じことができる。

insert()

位置を指定して様子を追加する。

insert(2, 'aaa')といった使い方をする、2がオフセット。

del

オフセットを指定して要素を削除する。

del aaa[1]といった使い方をする、delは文なのでaaa[1].del()とは書かない。

remove

値を指定して要素を削除する。

aaa.remove('A')といった使い方をする、Aが消える。オフセット位置が分からない場合などに利用。

pop

要素を取り出して削除する、取り出すので代入も可能。

In [20]: aaa = ['A','B','C']
In [21]: bbb = aaa.pop(0)
In [22]: bbb
Out[22]: 'A'

index

値を指定してオフセットを確認。

aaa.index.('A')といった使い方をする、Aのオフセットを返す。

in

値がリストの中に存在するかどうかを返す、同じものが複数存在している場合は1箇所でも同じものがあればTrueを返す。

In [38]: 'A' in aaa
Out[38]: True

count

特定の値がリスト内に何個含まれているかを返す。

aaa.count('探したい文言')などで検索する

sort/sorted

並べ替えをする、sortは元のデータを書き換える、sortedは元のデータを書き換えない

sortedの例

In [61]: aaa
Out[61]: ['ABC', 'XYZ', 'TW']

In [62]: sorted(aaa)
Out[62]: ['ABC', 'TW', 'XYZ']

In [63]: aaa
Out[63]: ['ABC', 'XYZ', 'TW']   並べ変わっていない

sortの例

In [63]: aaa
Out[63]: ['ABC', 'XYZ', 'TW']

In [64]: aaa.sort()

In [65]: aaa
Out[65]: ['ABC', 'TW', 'XYZ']   元のデータが並べ変わっている

In [67]: aaa.sort(reverse=True) reverse=Trueを付けると逆順になる

In [68]: aaa
Out[68]: ['XYZ', 'TW', 'ABC']

len

要素の数を返す

len(aaa)というように使う

=とcopy

リストの場合"="は代入なので、元が変わるとそれにつられて他のものも変わる

ただし通常の変数代入の場合はつられて変わらない

In [1]: aaa = ['A','B','C']

In [2]: aaa
Out[2]: ['A', 'B', 'C']

In [3]: bbb = aaa

In [4]: bbb
Out[4]: ['A', 'B', 'C']

In [5]: aaa[0] = '1'    リストaaaの0番目を1に変更

In [6]: aaa
Out[6]: ['1', 'B', 'C'] 0番目が1になっている

In [7]: bbb
Out[7]: ['1', 'B', 'C'] 元のデータが変わっているのでbbbも変わっている

In [8]: bbb[1] = 'Z'    bbbの1番目をZに変える

In [9]: bbb
Out[9]: ['1', 'Z', 'C']

In [10]: aaa
Out[10]: ['1', 'Z', 'C']    元のaaaの1番目もZに変わっている

copy関数、list()変換関数、リストスライスでコピーすると元の値が変わっても影響を受けない

In [11]: a = ['1','2','3']

In [12]: a
Out[12]: ['1', '2', '3']

In [13]: b = a.copy()   copy関数

In [14]: b
Out[14]: ['1', '2', '3']

In [15]: c = list(a)    list()変換関数

In [16]: d = a[:]   リストスライス

In [17]: a[0] = '8' 元データの0番目の値を変更

In [18]: a
Out[18]: ['8', '2', '3']    変わってる

In [19]: b
Out[19]: ['1', '2', '3']    影響なし

In [20]: c
Out[20]: ['1', '2', '3']    影響なし

In [21]: d
Out[21]: ['1', '2', '3']    影響なし