ホームページ >バックエンド開発 >Python チュートリアル >Python 開発者が Go に移行する前に知っておくべきこと
これは、Python/Cython コードの大部分を Go 言語に移行する経験を文書化した (長い) ブログです。ストーリー全体、背景などを知りたい場合は、読み続けてください。 Python 開発者が参加する前に知っておくべきことだけに興味がある場合は、以下のリンクをクリックしてください:
Python から Go に移行するためのヒントとコツ
背景
Repustate テクノロジーにおける私たちの最大の成果は、アラビア語の感情を実装したことです分析。アラビア語は本当に理解するのが難しく、単語の文法形式が複雑すぎます。アラビア語のトークン化(文を独立した単語に分割すること)は、英語などよりも困難です。これは、アラビア語の単語内(アレフの位置など)にスペースが含まれる場合があるためです。これは秘密にしておく必要はありません。つまり、Repustate はサポート ベクター マシン (SVM) を使用して文の最も可能性の高い意味を取得し、これに基づいて感情を分析します。合計 22 のモデル (22 のサポート ベクター マシン) を使用し、文書内のすべての単語が分析されました。言い換えれば、ドキュメントに 500 ワードが含まれている場合、10,000 を超えるサポート ベクター マシンの比較演算が行われることになります。
Python
Repustate は、アプリケーション プログラミング インターフェイスと Web サイトのアーキテクチャとして Django を使用しているため、ほぼ完全に Python で実装されています。したがって、コードの統一性を維持し、アラビア語の感情エンジン全体を Python で実装することしかできません。プロトタイピングと実装のプロセスでは、Python は依然として非常に優れています。非常に強力な表現能力と強力なサードパーティ ライブラリ リソース。 Web ページを提供するだけであれば、それでも完璧です。ただし、低レベルの計算を実行する必要があり、ハッシュ テーブル (Python の辞書) で多くの比較演算を実行する必要がある場合、速度は遅くなります。 1 秒あたり 2 ~ 3 件のアラビア語文書しか処理できませんが、これでは遅すぎます。これを、1 秒あたり 500 件のドキュメントを処理できる英語センチメント エンジンと比較してください。
ボトルネック
そこで、どの部分の実行が遅いのかを調査するために Python プロファイラーを開始しました。単語ごとに 22 のサポート ベクター マシンを使用すると言ったのを覚えていますか?これらのプロセスはすべてシリアルであり、並列操作はありません。さて、私たちの最初のアイデアは、これをmap/reduceのような操作に変更することです。簡単に言えば、map/reduce は Python には適していません。同時実行性が必要な場合、Python はまったく使いにくいです。 PyCon 2013 で、Guido 氏は、この問題を解決しようとする彼の新しいプロジェクトである Tulip について言及しましたが、それが開始されるまでにはしばらく時間がかかるでしょう。もっと良い選択肢がすでにあるのなら、なぜそれを待つ必要があるのでしょうか。
Go 言語に変更するか、家に帰ってファームしましょう
Mozilla の友人から聞いたところによると、ゴルーチンの力のおかげで、Mazilla サービスのロギング アーキテクチャのコードのほとんどが Go に切り替えられたそうです (Go糸)。 Go は、Python のさまざまなソリューションのような後付けではなく、並列処理を第 1 レベルの概念として扱うように、Google の人々のグループによって設計されました。そこで、Python を Go に変更し始めました。
Go コードはまだ実稼働レベルではありませんが、結果はすでに非常に有望です。毎秒 1000 ドキュメントに達し、メモリ使用量が減り、Python に付属する迷惑なマルチプロセス/gevent/「なぜ Ctrl+C でプロセスを強制終了したのか」コードに対処する必要がなくなりました。
私たちが Go に夢中になった理由
プログラミング言語がどのように動作するかについて少しでも知っている (解釈とコンパイル、動的と静的の違いを理解している) 人なら、「おいおい、Go の方が明らかに速い」と言うでしょう。 「。」確かに、すべてを Java で書き直して同様のパフォーマンスを得るということもできますが、それが Go が勝つ理由ではありません。 Go で作成したコードは簡単に正しいものになります。理由は説明できませんが、コードがコンパイルされると (コンパイル速度が非常に速いため)、それが機能することが実感できるでしょう (実行時にエラーが表示されないだけでなく、論理的に正しいということです)。奇妙に聞こえるかもしれませんが、本当です。これは、冗長性の問題を解決する (または冗長性がない) Python に似ており、関数を第 1 レベルのオブジェクトとして扱うため、関数型プログラミングを簡単に実行できます。 Go スレッドとチャネルにより、作業がとても簡単になります。また、静的型付けによってパフォーマンスが向上し、表現力を損なうことなくメモリ割り当てをより正確に制御できます。
知っておくべきだったこと
多くの賞賛にもかかわらず、Go を使用するには、Python を使用する場合とは異なる考え方が必要です。移行中のいくつかのメモは、Python を Go に変換するときにランダムに頭に浮かんだものです:
組み込みのコレクション型はありません (map を使用して存在を確認する必要があります)
コレクションがないためtype、交差、union などのメソッドを自分で実装する必要があります
タプルはありません、独自の構造体 (struct) を設計するか、スライス (配列と同様) を使用する必要があります
__getattr_() のようなメソッドはありません、存在を確認する必要がありますが、デフォルトの値を設定することはできません。たとえば、Python では次のように記述できます: value = dict.get("a_key", "default_value")
エラーをチェックする必要があります (または少なくとも明示的に無視する必要があります) )
未使用の変数やパッケージを持つことはできません。時々、一部のコードをコメントアウトする必要があります
[]byte と string を切り替えます。通常の処理 (正規表現) は []byte (書き換え可能) を使用します。これは正しいですが、前後に変換するのはまだ面倒です
Python の構文はより緩やかです。範囲外のインデックスを使用して文字列のフラグメントをエラーなく取得することも、負の数値を使用してフラグメントを取得することもできます。 Goではそうではありません。
混合型のデータ構造は使用できません。これは必ずしも適切ではないかもしれませんが、Python では、値が文字列とリストの混合である可能性のある辞書を使用することがあります。 Go ではなく、Go でデータ構造またはカスタム構造をクリーンアップする必要があります*
タプルやリストを別の変数 (例: x、y、x = [1, 2, 3]) に代入する方法はありません
ザトウクジラ式の大文字と小文字の規則 (最初の文字が大文字でない関数/構造体は他のパッケージに公開されません)。私は Python の小文字とアンダースコアの規則を好みます。
ブール型のように使用できる Python の多くの型 (0、空の文字列、None はブール "false" として使用できます) とは異なり、エラーが空かどうかを明示的にチェックする必要があります
一部のモジュール (crypo/md5 など) ) にはドキュメントが不十分ですが、IRC の go-nutes は非常に強力で、強力なサポートがあります
数値を文字列に変換する (int64->string) ことは、[]byte を文字列に変換する (string([]byte である限り) とは異なります)。 ) Go でコードを読み取るには strconv
を呼び出す必要がありますが、Python は疑似コードのように書くことができます。 Go では、or と and の代わりに || と && を使用して、英語以外の数字をさらに使用します。
ファイルの書き込みには File.Write([]byte) と File.WriteString(string) が含まれます。これは、問題を一方向で解決するという Python 開発者の信条と矛盾します。
文字列の挿入は使いにくいです。fmt.Sprintf を頻繁に使用する必要があります
コンストラクターはありません。通常は、必要な構造を返す NewType() 関数を作成するのが習慣です
Else (または else if) を使用する必要があります正しくフォーマットされている必要があります。else は、if に一致する中括弧と同じ行にある必要があります。奇妙さ。
関数の内部と外部で、= と := という異なる代入演算子が使用されています (翻訳者注: これは著者の誤解です。= と := の違いは、型が明示的に定義されているか、自動的に型推定されるかであり、関数の外側の変数は、関数は =) のみ使用できます
キーのリスト (dict.keys()) または値 (dict.values())、またはタプルのリスト (dict.items()) だけが必要な場合は、そこにありますGo には対応する関数がありません。自分で反復処理することしかできません