Yandexの翻訳APIを使ってみる(Pythonで)。

翻訳APIって使ってみたいけど無料でさっくり試せるやつが欲しいなと思ってた矢先、YandexのAPIであれば無料で使える噂を小耳にはさんだので、触ってみました。

後、日本語の文章が少なかったので、初学者向けに参考になれば幸いです。

翻訳してみた感じは結構微妙である。そのため、機械翻訳でいいから大量に文章を処理したいときにには便利かと思います。

あと、もっときれいに翻訳できるんだけど、っていう場合は見直すのでよろしくお願いします。 最後の翻訳テストは改行の文字コード\nを含んだ状態で翻訳しました。 https://translate.yandex.com/ で直接翻訳した時より精度が悪いため、原文も貼っておくので試しに翻訳してみてください。

規約のざっくり読み

まずは規約を読んどこう。安全のために。

  1. 提供してる機能の範囲内で使っていて、規約を守れば商用利用可

  2. 逆コンパイルとかプログラム改変は不許可?多分、普通に使っていれば関係ない?

  3. 上限は以下の文字数。1日と1か月の制限を共に受ける。格安SIMの通信容量みたいな感じだね。

    • 100万文字/1日

    • 1000万文字/1か月

    文庫本一冊が10万文字といわれてるから、1か月で大体100本の文庫本も翻訳できるみたいね。こんなに大量に翻訳しても翻訳済みの文章すら読み切れなさそう。外国語データの処理とかでもしない限り大丈夫そうだね。ちなみに六法全書は およそ3500万字?3600万文字らしいから専門書丸々の翻訳とかをするときには足りないかもね。

  4. 文字数制限は事前通知アリで変更される可能性があるらしい。

  5. テキスト量やアクセス元の数が制限を超えたらYandex側からサービス提供を拒否されるよ。アクセス元の数のついては特に書いてないので複数プログラムに組み込むときは要注意?

  6. 法律違反してるコンテンツ、データの翻訳はダメよ。ちなみに法律は ロシア連邦の法律と住んでる国の法律だね。

  7. 使用した場合は下記の画面に「 Powered by Yandex.Translate 」の形で、 クリックっするとhttp://translate.yandex.com へ飛ぶように設定し、メインのテキストと同じフォントサイズ、色に設定すること。また、表示されるように設定すること。

    • ソフトウェアアプリケーションの説明

    • 各ヘルプトピック

    • ソフトウェアアプリケーションの公式Webサイト

    • サービスのデータが表示されるすべてのページ/画面

    多分、こんな感じ↓

    Powered by Yandex.Translate

    これは内部アプリケーションで使用するときも守るべきだろうけど、外部リリースするときにとりわけ慎重にチェックすべき項目だね。

  8. 翻訳サイト https://translate.yandex.com/ と同等の機能を持つサイト、サービス、アプリの構築に使っちゃだめよ。

  9. 事前通知なしにサービスの変更、修正、または更新がされる可能性アリ。

    次バージョンのリリースはYandexのWebページで発表される。

    新バージョンの使用に同意できない場合は、旧バージョンの安定性と動作能力を保証しないが、自己責任で旧バージョンを継続して利用できる。もちろん、コードを削除して別サービスに移行してもかまわない。

  10. 利用規約の違反判定は、独自の裁量により行われ、通知または理由の説明なしにサービスへのアクセスを終了または一時停止される。

大体こんな感じ。ちゃんと読んでおくべきなので https://yandex.com/legal/translate_api/ にアクセスして各自読むこと。組み込むなら https://translate.yandex.com/ で翻訳してでもちゃんと読んどこう。

あと、大事そうなところ。そもそも全部大事だけどね。

  • 守るべき法律はロシア連邦の法律と住んでる国の法律の2つとも(1.3を参照)。

  • 何かしらの判断はロシア連邦の法律に基づく(1.4を参照)。

  • 同意なしにユーザーのロゴとか商標とか使うけどお金は払うよ(3.3を参照)。

  • 規約変更した場合、最新の規約を遵守すること(5.2を参照)。

導入(アカウント作成など)

規約を読んだらひとまず導入してみよう。

まず、 https://tech.yandex.com/translate/ にアクセス。

あとは書いてある通りの手順でOK。APIを叩くには③から実行すればいい。

ログインかアカウント作成、SNSアカウントでログインを行うこと。今回はTwitterでログイン。「連携アプリを認証」を押して、

次に出てくる「I’m a new user」を押す。

すると以下のページに出るので、「Create a new key」を押すと、

以下のようなウィンドウが出る。今回は「translation_test」と記入した。

するとAPIキーが発行された。このAPIキーは外部に漏らさないように。

かなりさっくりAPIキーを発行できた。上部に表示されるように、paid versionでは上記文字数制限を突破することが出来るらしい。

使い方

普通にAPI叩きます。
ただ、僕は自力でAPIを叩けません。 なので参考サイトを基に作りましょう。

参考

ここを参考にします。というか、ここを読んだ方が早いです。 https://www.digitalocean.com/community/tutorials/how-to-get-started-with-the-requests-library-in-python

ちなみに公式ドキュメントはこちらです。適宜修正するために参考にして下さい。
翻訳についてはこちらを参照。

requestsの仕方

仕組みとしては、requestsのparamsに各種パラメーターを入れた辞書を渡して、APIのURLに送るだけでいい。最後のres.json()を入れると、翻訳結果をdict型で取り出すことが出来る。

 import requests
 url = 'https://translate.yandex.net/api/v1.5/tr.json/translate'
 
 API_KEY = "paste your api key"
 params = dict(key=API_KEY, text='Hello!?', lang='en-ja')
 
 res = requests.get(url, params=params)
 print(res.json())

結果

 {"code":200,"lang":"en-ja","text":["こんにちは!?"]}

意味としては、以下の通り。

code : 応答コード。200なら正常終了。詳細はここ
lang : 翻訳言語の設定。自動翻訳をしたときに確認が必要かも?
test: 翻訳結果。list型

 

また、requestsがひつようなので、各自CMDからインストールすること。

 pip install requests

paramsの設定

辞書に入れる内容は以下。

  1. key APIキー

    上で取得したキーを設定。

  2. text テキスト

    POSTなら一回で最大 10,000文字 まで。

    GETなら 2〜10 KB の範囲まで。

    ただし、 すべての特殊文字はエスケープする必要がある。 Pythonだとバックスラッシュでいいけど、こっちもそれでいいの? あと、「!」とか「?」程度ならエスケープしなくていいっぽい。

  3. lang 言語設定

    言語は短縮の2文字で指定する。国名はこちらを参照。

    • 言語指定時

      翻訳元と翻訳先の国名を指定。英語から日本語に翻訳する時は “en-ja”

    • 翻訳元言語の自動検出時

      翻訳先の国名のみを指定。日本語翻訳時は “ja”

  4. format テキストフォーマット

    入力するテキストのフォーマットを指定できます。

    • plain -通常のテキスト(デフォルト)

    • html -HTML形式のテキスト。ちなみに小文字だからな。

  5. options オプション

    翻訳元の言語を自動検出するならここを「1」にする。

  6. callback コールバック

    ごめん、これわかんない。「 コールバック関数の名前。JSONP応答を取得するために使用します。 」だってさ。

params設定例

例1 通常翻訳

 params = dict(key=API_KEY, text='Hello!?', lang='en-ja')

もちろん書き方はこっちでもいい。

 params = {}
 params["key"]=API_KEY
 params["text"]="Hello!?"
 params["lang"]="en-ja"

結果

 {"code":200,"lang":"en-ja","text":["こんにちは!?"]}

例2: 自動翻訳

 params = {}
 params["key"]=API_KEY
 params["text"]="Hello!?"
 params["lang"]="ja"
 params["options"]=1

結果

 {"code":200,"detected":{"lang":"en"},"lang":"en-ja","text":["こんにちは!?"]}

HTML翻訳

 params = {}
 params["key"]=API_KEY
 
 HTML_text = """<!DOCTYPE html>
 <html lang="ja">
  <head>
    <meta charset="UTF-8">
    <title>HTMLのタイトル</title>
  </head>
  <body>
    <h1>HTMLの書き方</h1>
    <p>はじめてのHTMLを作りました</p>
  </body>
 </html>"""
 
 params["text"]=HTML_text
 params["lang"]="ja-en"
 params["format"]="html"

HTMLの文章はここから拝借しました。 元コード

 <!DOCTYPE html>
 <html lang="ja">
   <head>
     <meta charset="UTF-8">
     <title>HTMLのタイトル</title>
   </head>
   <body>
     <h1>HTMLの書き方</h1>
     <p>はじめてのHTMLを作りました</p>
   </body>
 </html>

元ページ 

結果

 {"code":200,"lang":"ja-en","text":["<!DOCTYPE html>\n<html lang=\"ja\">\n  <head>\n    <meta charset=\"UTF-8\">\n    <title>The HTML title</title>\n  </head>\n  <body>\n    <h1>HTML how to write</h1>\n    <p>For the HTML made</p>\n  </body>\n</html>"]}

これをPythonでテキストとして保存してあげればいい。

 <!DOCTYPE html>
 <html lang=\"ja\">
     <head>
         <meta charset=\"UTF-8\">
         <title>The HTML title</title>
     </head>
     <body>
         <h1>HTML how to write</h1>
         <p>For the HTML made</p>
     </body>
 </html>

ちゃんと翻訳された。

ちなみに、formatを”plain”に設定した場合の結果

 <! DOCTYPE html>
 <html lang="EN">
 the <head>
 <meta charset="UTF-8">
 the <title>HTML title</title>
 </head>
 the <body>
 the <h1>HTML how to write</h1>
 <p>for the HTML to make</p>
 </body>
 </html>

なんか「the」がいっぱい入った。

おわりに

大体こんな感じ。 意外と簡単に翻訳できるようになる。

この辺りを好きに組み立てて翻訳すれば簡単に大量の文章を翻訳できる。

最後に翻訳精度を見るために、いくつかのパブリックドメインな文章を翻訳してみたので参考にしてほしい。

それでは。

翻訳例

ここの文章は著作権切れか著作権フリーのものを使用しました。 https://translate.yandex.com/ で直接翻訳した時より精度が悪いため、原文を使って試しに翻訳してみてください。

不思議の国のアリス(Alice’s Adventures in Wonderland by Lewis Carroll)

https://www.gutenberg.org/files/11/11-h/11-h.htm 冒頭の3段落分

原文

 CHAPTER I.
 Down the Rabbit-Hole
 Alice was beginning to get very tired of sitting by her sister on the bank, and of having nothing to do: once or twice she had peeped into the book her sister was reading, but it had no pictures or conversations in it, “and what is the use of a book,” thought Alice “without pictures or conversations?”
 
 So she was considering in her own mind (as well as she could, for the hot day made her feel very sleepy and stupid), whether the pleasure of making a daisy-chain would be worth the trouble of getting up and picking the daisies, when suddenly a White Rabbit with pink eyes ran close by her.
 
 There was nothing so very remarkable in that; nor did Alice think it so very much out of the way to hear the Rabbit say to itself, “Oh dear! Oh dear! I shall be late!” (when she thought it over afterwards, it occurred to her that she ought to have wondered at this, but at the time it all seemed quite natural); but when the Rabbit actually took a watch out of its waistcoat-pocket, and looked at it, and then hurried on, Alice started to her feet, for it flashed across her mind that she had never before seen a rabbit with either a waistcoat-pocket, or a watch to take out of it, and burning with curiosity, she ran across the field after it, and fortunately was just in time to see it pop down a large rabbit-hole under the hedge.

結果

 第章
 Down the Rabbit-Hole
 アリスをはじめとした大変おいしくいただけましたの疲れを座って姉の日本銀行にともないまっ願をした姉が明らかにしてくれるものではない写真や会話の中で、何を書けている"とアリス"な写真や会話?"
 
 うした考えに彼女自身の心がどのように暑い日を心で感じ取ってくれました眠たくて、かかる愉しみのデイジーチェーンが価値があるとのトラブルの上で、daisiesが突然白うさぎとピンクの目の走りによります。
 
 なので非常に顕著となったアリスのようなものを聞いて、うさぎと言うの、"まあ! まあ! 私は、できることを確認します。" きていると思っていたので、その後、原発事故が明らかにした彼女は彼女がいうんですが、その時にでもなかなか自然ができた場合写実した時のチョッキ-ポケットを見たので、急ぎで、アリスを始めた彼女の足で出彼女の心がなかった前を見ているうさぎのいずれかのチョッキ-ポケット、時計への送料のご負担を軽減するため、燃焼、好奇心 ったので、幸いだった時間でア大うさぎの穴の下でリスクがあります。

白鯨(Moby-Dick;or, The Whale. by Herman Melville )

https://www.gutenberg.org/files/2701/2701-h/2701-h.htm#link2HCH0001 冒頭の3段落分

原文

 CHAPTER 1. Loomings.
 Call me Ishmael. Some years ago—never mind how long precisely—having little or no money in my purse, and nothing particular to interest me on shore, I thought I would sail about a little and see the watery part of the world. It is a way I have of driving off the spleen and regulating the circulation. Whenever I find myself growing grim about the mouth; whenever it is a damp, drizzly November in my soul; whenever I find myself involuntarily pausing before coffin warehouses, and bringing up the rear of every funeral I meet; and especially whenever my hypos get such an upper hand of me, that it requires a strong moral principle to prevent me from deliberately stepping into the street, and methodically knocking people’s hats off—then, I account it high time to get to sea as soon as I can. This is my substitute for pistol and ball. With a philosophical flourish Cato throws himself upon his sword; I quietly take to the ship. There is nothing surprising in this. If they but knew it, almost all men in their degree, some time or other, cherish very nearly the same feelings towards the ocean with me.
 
 There now is your insular city of the Manhattoes, belted round by wharves as Indian isles by coral reefs—commerce surrounds it with her surf. Right and left, the streets take you waterward. Its extreme downtown is the battery, where that noble mole is washed by waves, and cooled by breezes, which a few hours previous were out of sight of land. Look at the crowds of water-gazers there.
 
 Circumambulate the city of a dreamy Sabbath afternoon. Go from Corlears Hook to Coenties Slip, and from thence, by Whitehall, northward. What do you see?—Posted like silent sentinels all around the town, stand thousands upon thousands of mortal men fixed in ocean reveries. Some leaning against the spiles; some seated upon the pier-heads; some looking over the bulwarks of ships from China; some high aloft in the rigging, as if striving to get a still better seaward peep. But these are all landsmen; of week days pent up in lath and plaster—tied to counters, nailed to benches, clinched to desks. How then is this? Are the green fields gone? What do they here?

結果

 第1章 Loomings.
 Call me Ishmael. 数年前にはない独自路線を貫いているのかを正確に持っていないお金は私の財布にも特に興味がなくて海岸にあうと思い出航しょうと、水の一部です。 もうかっているところにしていまの車の脾臓を調節する。 いつか自分に厳しい成長の口腔いただくことができま湿霧月に私の魂;ます私も思わず一時停止の前に棺倉庫をリアの葬儀に出会えると、特にもっhyposのような上方の私が持っているのでコラボレーションが必要であり道徳原理の防止から意図的にステッピングのストリート、methodicallyノック人の帽子をオフにした口座でには時間を海とができます。 これが私の代替ピストルとボール。 と哲学の活躍ーカトー投者剣;I静かにのる。 あり驚きです。 いものであることを知っていて、ほとんどの男性は、一部の時間又はその他を大切にしてもほぼ同じ想いで海に向かった。
 
 し、その結果については島市のManhattoes,丸ベルトによる,としてインド諸島のサンゴ礁—商業を取り巻く彼女のサーフィンです。 左右の魅力を存分におwaterward. その極端なダウンタウンは、電池が置かれているが、その崇高なモールの洗浄による波の冷却風を数時間前の姿。 を見て勢の水gazersあります。
 
 Circumambulateの街で夢のような安息日午後にありました。 からCorlearsクCoenties滑り、故により、Whitehall,北. 何でしょうか?—掲載のように静かsentinels街、スタンドの人の必殺技では男性固定オーシャンリヴァリエ. 一部の傾きに対するspiles一座のピア-ヘッドの一部が見渡せるbulwarksの船の中国から、高アロフト、リギングという努めるものよりよい海側ののぞき窓. これらはすべてlandsmen;曜日ペッ旋盤、漆喰につカウンターに釘で打ベンチリにデスクがあります。 どうしてでしょうか。 のグループへ行ってしまったのでしょうか。 何ですか?

以下はWikinewsの記事の中で閲覧時に最初の方にあったもの

サイエンス記事(Ancient Egyptians collected wild ibis birds for sacrifice, says study)

https://en.wikinews.org/wiki/Ancient_Egyptians_collected_wild_ibis_birds_for_sacrifice,_says_study

原文

 Ancient Egyptians collected wild ibis birds for sacrifice, says study   
 Saturday, November 16, 2019
 In findings published on Wednesday in the journal PLOS ONE, an international team of scientists report ancient Egyptians captured sacred ibises (Threskiornis aethiopicus) from the wild for use in ritual sacrifice rather than domesticating the birds.
 Millions of mummified ibis birds have been found in Egyptian tombs and catacombs in Saqqara and Tuna el-Gebel, and Egyptologists have reported they were sacrificed to the god Thoth, who is often depicted with the head of an ibis, the way Horus is shown with the head of a falcon and Bast with the head of a cat.
 Lead author Sally Wasef of Australia's Griffith University explained to the press, "The ibis was considered [to represent] the god Thoth, the god of wisdom, the god of magic, the god of judgment, writing all sorts of things [...] If you had a boss that annoys you and you don't feel like you are getting a good judgment from him or you want fairness and justice, you go and ask Thoth to interfere and in return you promise to offer him an ibis, a mummified ibis, in his annual feast."

結果

 古代エジプトで収集した野生の鳥イビスのために犠牲と研究 
 土曜日、16日2019年
 で成果を刊行の雑誌PLOS ONEは、国際チームの研究者報告書の古代エジプトで捕獲した霊羽(Threskiornis aethiopicus)から、野生のための使用に儀式を犠牲にしよdomesticatingします。
 単位百万mummifiedイビス鳥についてエジプトの墓には、カタコンベ、サッカラ-マグロ-エル-Gebel、Egyptologistsて報告されたものを捧げる神Thoth、しばしば描かれたのは、イビスのホルスが表示され、ファルコン、州特別大隊第二次世界大戦博物の猫です。
 鉛筆者サリー Wasefオーストラリアのグリフィス大学についての説明は、"イビスのたれ【代表】神Thoth、神の知恵は、神の魔法の判断を作ったり、いろんなもので[...]だった上司がニがまんが入ってしまったような感覚を取って判断から計らってダッシュでかわしたり、また公平と正義は、以下から入手できます、お願いThoth干渉しますを提供することをお約束という自身にとってのイビス, a mummifiedイビスは、彼の年になるのかもしれません。"

健康保険の記事(World Health Organization names new coronavirus COVID-19)

https://en.wikinews.org/wiki/World_Health_Organization_names_new_coronavirus_COVID-19

原文

 World Health Organization names new coronavirus COVID-19
 Friday, February 14, 2020
 On Tuesday, the World Health Organization (WHO) announced the official name of the coronavirus-induced disease first recognized about two months ago in Wuhan, China: "COVID-19" is to replace the WHO's temporary designation "2019-nCoV."
 "COVID-19" is the name of the disease rather than the virus. The International Committee on Taxonomy of Viruses named the virus that causes it "severe acute respiratory syndrome coronavirus 2" (SARS-CoV-2)
 Reportedly, "COVI" represents the coronavirus, "D" is for "disease," and "19" for the year it was first detected, 2019.
 WHO director-general Tedros Adhanom Ghebreyesus said the name had to be easy to say and, to prevent stigma, it must not cite any specific person, animal, profession or place, per WHO guidelines established in 2015.

結果

 世界保健機関の名称新coronavirus COVID-19
 金曜日,月14日2020年
 日(火)、世界保健機関(WHO)に発表の正式名称coronavirus誘発症された最初の約二ヶ月前には、大きく二つに分けられて:"COVID-19"が置換した方が仮設定"2019年-nCoV."
 "COVID-19"の名前の病気ではなく、ウイルス 国際委員会の分類のウイルスのウイルスを原因となるが"重症急性呼吸器症候群coronavirus2"(SARS-CoV-2)
 れるそう"COVI"のcoronavirus"D"で"疾病"と"19"の年で最初に検出し、2019年に
 人長Tedros Adhanom Ghebreyesusの名することをサポートすることを言って、スティグマまでもなく、わが国は、引用特定の人、動物、一専門職務、または、一人のガイドライン開設2015年までに

政治の記事(Joe Biden wins 2020 South Carolina US Democratic presidential primary)

https://en.wikinews.org/wiki/Joe_Biden_wins_2020_South_Carolina_US_Democratic_presidential_primary

原文

 Joe Biden wins 2020 South Carolina US Democratic presidential primary
 Monday, March 2, 2020
 On Saturday, former Vice President of the United States Joe Biden won the Democratic Party's South Carolina primary election. The Democratic Party uses primary elections, along with caucuses, to select its nominee for the 2020 United States presidential election.
 Biden secured 39 of South Carolina's 54 delegates with about 48% of the vote, giving him a total of 54 delegates. United States Senator from Vermont Bernie Sanders came in second, with about 20% of the vote earning 15 delegates for a running total of 60. Tom Steyer came in third, receiving roughly 11% of the votes.
 The South Carolina primary was the fourth step in the Democratic party's primary election cycle. In Iowa, caucuses where held on February 3, and in New Hampshire, a primary election was held on February 11. Nevada held its caucuses on February 22.

結果

 ジョー Biden勝2020年までの米国サウスカロライナ州で民主党主
 月曜日、月2日2020年
 日(土)元副会長、米国ジョー Bidenの民主党のサウスカロライナ州一次選とする。 民主党の使用次の選挙は、caucusesを選択でき、その候補者は、2020年までの米国の大統領選とする。
 Biden確保39のサウスカロライナ州の54の代表団は約48%の投票のたる合計54いただけます。 米国上院議員からバーモントBernie Sandersた第二に、約20%の投票の収益15派遣オペレーティングシステムは合計60. Tom Steyerた第三に、約11%にするものである。
 南カロライナ次のステップは、民主党の選挙サイクルです。 アイオワ州,caucusesが開催3月、ニューハンプシャー、一次選挙月11. ネバダを開催しcaucuses月22.

Powered by Yandex.Translate

「psd2waifu2x」ソースコード

これらのソースコードは改変などは基本的に自由に行ってもらって構いません。
ただ、改善や機能追加等をして頂けた場合は、僕自身興味がありますのでコメント欄などにご一報いただけると幸いです。


psd2wife.py


#coding:utf-8

from psd_tools import PSDImage
import os, copy, subprocess, datetime, glob, sys
from configparser import ConfigParser

class PSDPaser:
    def __init__(self, dir_psd, dir_cfg = os.path.join(os.path.dirname(__file__), "psd2wife.ini"), safe_mode = True):
        self.config = ConfigParser()

        self.config.read(dir_cfg, "utf-8")
        self.wf_scale = float(self.config.get("waifu", "wife_scale"))
        self.dir_safe = self.config.get("save", "safety")

                
        self.dir_psd = dir_psd
        self.psd = PSDImage.open(dir_psd)

        self.psd_all = [i for i in self.psd.descendants()]
        
        if safe_mode:
            self.dir_save_base  = os.path.join(self.dir_safe, datetime.datetime.today().strftime("%Y%m%d_%H%M_%S"))
        else:
            self.dir_save_base = self.dir_psd.replace(".psd", "")
        self.dir_save_pics  = os.path.join(self.dir_save_base, "result") 
        
        list_file_name = []
        
        structure = []
        structure_all = []
        structure_hrchy = []
        
        structure_safe = []
        structure_safe_all = []
        structure_safe_hrchy = []
        psd_setting=[[str(int(self.psd.width * self.wf_scale)), str(int(self.psd.height * self.wf_scale))]]
        
        print("「{}」\nに.psdの各レイヤーを画像に変換します。".format(self.dir_save_pics))
        for psd_elem_num, psd_elem in enumerate(self.psd_all):
            if str(psd_elem.parent.name) == "Root":
                structure = []
                
            loop=0
            structure = []
            structure_safe = []
            
            psd_group = copy.deepcopy(psd_elem.parent)
            while psd_group.is_group():
                loop+=1
                structure.append(psd_group.name)
                if str(psd_group.name) != "Root":
                    psd_group = psd_group.parent
                else:
                    break
            try:
                structure.remove("Root")
            except:
                pass
                
            file_name = psd_elem.name
            list_file_name.append(file_name)
            
            if safe_mode:
                for i in structure:
                    if structure_all.count(i) == 0:
                        structure_all.append(i)
                    structure_safe.append("Group_{}".format(str(structure_all.index(i)+1)))
                for i in structure_safe:
                    if structure_safe_all.count(i) == 0:
                        structure_safe_all.append(i)
            
            if structure_hrchy.count(structure) == 0 and structure != []:
                structure_hrchy.append(structure)
                
                structure_safe_hrchy.append(structure_safe)
                
            if safe_mode:                
                structure = structure_safe
                file_name = "layer_{}".format(str(psd_elem_num+1))
                
            os.makedirs(os.path.join(self.dir_save_pics, *structure[::-1]), exist_ok=True)
            dir_save = os.path.join(self.dir_save_pics, *structure[::-1], file_name + ".png")
            psd_setting.append([dir_save, str(int(psd_elem.offset[0] * self.wf_scale)), str(int(psd_elem.offset[1] * self.wf_scale)), "_".join([*structure[::-1], file_name]), str(int(psd_elem.is_visible())), structure[0] if structure != [] else "this_is_base_group"])
            if not psd_elem.is_group():
                try:
                    layer = psd_elem.topil()
                    layer.save(dir_save)
                except:
                    print("{}は保存されませんでした。".format(psd_elem.name))
                    
        self.gimp_structure_all = "[\"{}\"]".format("\",\"".join(structure_all))
        self.gimp_structure_hrchy = "[{}]".format(",".join(["[\"{}\"]".format("\",\"".join(i)) for i in structure_hrchy]))
        self.gimp_structure_safe_all = "[\"{}\"]".format("\",\"".join(structure_safe_all))
        self.gimp_structure_safe_hrchy = "[{}]".format(",".join(["[\"{}\"]".format("\",\"".join(i)) for i in structure_safe_hrchy]))
        
        self.gimp_file_name = "[\"{}\"]".format("\",\"".join(list_file_name[::-1]))
                
        print("変換終了")
        str_ = "\n".join([",".join(i) for i in psd_setting])
        self.dir_save_setting = self.dir_save_pics+".txt"
        with open(self.dir_save_setting, "wt") as f:
            f.write(str_)

        
    def waifu_run(self):
        dir_waifu = self.config.get("waifu", "directory")
        try:
            cmd="\"{}\" -i \"{}\" -s {} {}".format(dir_waifu, self.dir_save_pics, str(self.wf_scale),self.config.get("waifu", "setting"))
        except:
            cmd="\"{}\" -i \"{}\" -s {}".format(dir_waifu, self.dir_save_pics, str(self.wf_scale))
        print("「{}」を実行します。しばらく時間が借るので放置してください。".format(cmd))
        subprocess.call(cmd)
        
    def gimpImportCommand(self):
        dir_converted = glob.glob(self.dir_save_pics+"*"+ os.sep)
        os.rename(self.dir_save_pics, self.dir_save_pics+"_preWaifu2x")
        os.rename(dir_converted[1], dir_converted[0])
        
        dir_save_gimp_cmd = os.path.join(self.dir_save_base, "gimp_cmd.txt") 
        dir_save_gimp = self.dir_save_setting.replace(".txt", ".xcf")
        gimp_cmd='''import codecs
dir_txt = r"{}"
dir_save = r"{}"

structure_all = {}
structure_hrchy = {}
structure_safe_all = {}
structure_safe_hrchy = {}

gimp_file_name = {}

with codecs.open(dir_txt, 'r', 'utf-8', 'ignore') as f:
    im_setting = f.read()

list_ims = [i.split(",") for i in im_setting.split("\\n")]
image = gimp.Image(int(list_ims[0][0]), int(list_ims[0][1]), RGB)

list_group=[pdb.gimp_layer_group_new(image) for i in structure_safe_all]

for i in range(len(list_group)):
    #list_group[i].name = structure_safe_all[i]
    list_group[i].name = structure_all[i]

base_group = []
list_hierarchy = []
for i in range(len(structure_safe_hrchy)):
        if len(structure_safe_hrchy[i])>1:
            list_hierarchy.append(structure_safe_hrchy[i])
        else:
            base_group.append(structure_safe_hrchy[i])

base_group = base_group[::-1]
list_hierarchy = list_hierarchy[::-1]
for  i in range(len(base_group)):
    image.add_layer(list_group[structure_safe_all.index(base_group[i][0])], i)


list_remove = []
for i in range(len(list_hierarchy)):
    test = list_hierarchy[i][::-1]
    if len(test)>1:
        for j in range(len(test)-1):
            check=[test[j+1], test[j]]
            if not check in list_remove:
                list_remove.append(check)
                group_check = [list_group[structure_safe_all.index(check[0])], list_group[structure_safe_all.index(check[1])]]
                pdb.gimp_image_insert_layer(image, group_check[0], group_check[1], i)
                print(check)

gimp.Display(image)

for num_setting in range(len(list_ims[1:][::-1])):
    layer_setting = list_ims[1:][::-1][num_setting]
    try:
        layer = pdb.gimp_file_load_layer(image, layer_setting[0])
        layer.set_offsets(int(layer_setting[1]), int(layer_setting[2]))
        layer.name = gimp_file_name[num_setting]
        pdb.gimp_drawable_set_visible(layer, int(layer_setting[4]))
        
        key = layer_setting[5].replace("\\r","")
        gimp.message(key)
        if key == "this_is_base_group":
            image.add_layer(layer, num_setting)
        else:
            pdb.gimp_image_insert_layer(image, layer, list_group[structure_safe_all.index(key)], num_setting)

    except:
        pass

drawable = pdb.gimp_image_get_active_layer(image)
pdb.gimp_xcf_save(0, image, drawable, dir_save, dir_save)

gimp.Display(image)

'''.format(self.dir_save_setting, dir_save_gimp, self.gimp_structure_all, self.gimp_structure_hrchy, self.gimp_structure_safe_all, self.gimp_structure_safe_hrchy, self.gimp_file_name)


        with open(dir_save_gimp_cmd,"w",encoding="utf-8") as gimp_file:
            gimp_file.write(gimp_cmd)
        subprocess.run("explorer {}".format(self.dir_save_base))



if __name__=="__main__":
    print("グループ名が重複しているとバグが発生して正常に変換できません。\n手動でPSDファイルを編集して、グループ名が重複しないようにリネームしてください。\n(例: 「Group」→「Group #1」)")
    print("もしくは1度Gimpでpsdファイルを開き、再エクスポートしてください。\n重複が自動で解決されます。")
    dir_psd = input("waifu2xで変換したい.psdファイルをD&DしてEnterを押してね!")
    psdp = PSDPaser(dir_psd)
    psdp.waifu_run()
    psdp.gimpImportCommand()

psd2wife.ini


[save]
safety=G:\Dev_Doc\gimp
[waifu]
directory   = O:\files\waifu2x-caffe\waifu2x-caffe-cui.exe
wife_scale  = 2.0

psd2waifu2x配布・サポート(?)ページ

こんにちは、鐵火卷です。

このページは先日公開いたしました「psd2waifu2x」の配布、サポートページとなっています。

配布

「psd2waifu2x」は以下のonedriveよりダウンロード可能です。
https://1drv.ms/u/s!AsMZ4BamVPJEgTMsrM3wn266tDUT

また、別ページのソースコードをコピペして使用してください。

動作環境

windows (10でのみチェック)
Python 3.x系列 (3.7でのみチェック)
Gimp (インストール版でのみチェック)
waifu2x-coffee

使い方

動画を参照してください。

サポート

困ったことがあれば、コメント欄に記載していただければと思います。
ただし、以下の内容についてはお答え出来かねます。

・動作確認など(特に、このスペックで動作しますか?といった質問)
・GUI作って!
 → 初学者なので現状は無理です。数年後 or 別の人に頼んでください。
・ポータブルにしてほしい!
 →ironpythonとgimpのポータブルとかでも行けるんですかね?誰か検証してください。
・Gimpのpython上ですべて完結すればいいのでは?
 →gimpで日本語のファイルとディレクトリを扱えるようにする手段をだれか教えてください…

FAQ?

Q1. グループ名が被っているとGimpでの再構成でエラーが出る
A1. Gimpで一度.psdファイルを開き、.psdとしてエクスポートしてください。
Gimpは同じ名前のグループ、レイヤーを作成することが出来ません。
ですので、.psdファイルを開くだけで自動的にリネームしてくれます。

Q2. Gimpでレイヤーが読み込まれない
A2. 保存先として設定したディレクトリに非アスキー文字が含まれているためです。
ディレクトリに半角英数しか含まれていないことを再度確認してください。
場合によっては半角スペースもエラーの原因かもしれません。

Q3. Pythonのプログラムでエラーが出る。
A3. それ、Pythonの2.x系列じゃないよね?
あと、要求されるモジュールもインストールしてね。
場合によってはpipのアップデートが出来てないのかも?

Blender2.8のPythonにモジュール類を簡単に移行するには

こんにちは、鉄火巻です。

前の記事では、Blender内のPythonにモジュールをインストールする方法を紹介しました。

ここでは、通常のPyhtonで使っているモジュールをBlenderに移行するとき、バージョンなどを指定しながらいちいち移していく面倒を解決する方法です。
といっても、よくあるやり方です。

手順

これはシンプル。まずは、通常のpythonの環境から各種モジュールのバージョンを記載したテキストファイルを生成しましょう。

python -m pip freeze > requirement.txt

生成先は指定できるので、取り出しが面倒であれば、直接Blenderのあるフォルダに生成してあげましょう。

python -m pip freeze > "O:\files\blender-2.80.0-git.99d4321feff6-windows64\2.80\python\bin\requirement.txt"

次に、cd, cd/dなどで移動して、

cd/d  
O:\files\blender-2.80.0-git.99d4321feff6-windows64\2.80\python\bin

pipからインストールしましょう。
前の記事でも書きましたが、Blender側からモジュールを読み込むには–userのオプションが必須です。

 python.exe -m pip install -r requirements.txt --user 

以上です。特に難しいってわけではなさそうだね。

それでは、鉄火巻でした。

Blenderに搭載されているPythonにpipを導入しよう(Windows10, ポータブル版)

こんにちは、鉄火巻です。

最近Blenderを触っているんですが、外部のモジュールをどうしても使いたいのでpipを導入しようと思います。といっても、参考サイトとやってることは同じだし、特に変なことはしていません。

手順

以下をcmdで実行しましょう。管理者権限はあった方がいいんじゃないかな? Blender2.8を使用しているため、ディレクトリはProgramfileではありません。いわゆるポータブル版です。 インストーラーを使ってインストールすればProgramfileのどこかに同じようなフォルダがあるでしょう。

 "O:\files\blender-2.80.0-git.99d4321feff6-windows64\2.80\python\bin\python.exe" -m ensurepip

すると以下のようにpipとsetuptoolsがインストールされます。ただし古いバージョンです。

C:\WINDOWS\system32>"O:\files\blender-2.80.0-git.99d4321feff6-windows64\2.80\python\bin\python.exe" -m pip list
Package Version
---------- -------
pip 10.0.1
setuptools 39.0.1

ですので、以下のようにそれぞれアップデートしてあげましょう。これも特に変わったことではありません。

 "O:\files\blender-2.80.0-git.99d4321feff6-windows64\2.80\python\bin\python.exe" -m pip install --upgrade setuptools pip

これで最低限pipはインストールできました。pythonから環境を移行するときは以下のように主環境でrequests.txtを生成してやればよいでしょう。

この辺のモジュール(https://qiita.com/haminiku/items/5187713bba6cb30532bf)を入れておくと便利でしょう。

注意) –userのオプションが必要

pipの触り方は以上のように、Blender内のpythonを直接たたけばよいのですが、以下のようにモジュールをインストールすると、Blenderからimportする時にエラーを吐きます。

".../python.exe" -m pip install [module name]

調べたところ、インストールには–userのオプションが必要です。面倒ですが、毎回、以下のようにインストールしましょう。

 ".../python.exe" -m pip install [module name] --user

参考

https://www.kunihikokaneko.com/dblab/cg/bpypip.html

https://blenderartists.org/t/how-to-install-python-packages-with-pip-blender-2-8/1142721/3

余談

当たり前ですけど、以下からpythonのバージョンは確認可能です。

 "O:\files\blender-2.80.0-git.99d4321feff6-windows64\2.80\python\bin\python.exe" -V

多分ですけど、主環境と同じpythonが入るみたいですね(ポータブルだからかな?)。僕の環境では3.7.0って返ってきました。


以上です。pipがあれば開発が捗りますね。 必要なモジュールが入れば開発の幅は一気に広がりますね。

それでは、鉄火巻でした。

関連記事

pythonで感情分析に入門

こんにちは、クロガネです。

皆さん、ネットを徘徊していて書いてある文章にどんな感情が込められているのか?ということが気になったことはないでしょうか?

まあ、文学に精通している人であれば言葉の表現のみで大体わかるんでしょうけど、僕の場合は特に文学的な部分は触れずに育ってしまったので言葉に堪能ではありません。

とはいえ、感情を読み取ることは人間生活において重要であることは変わりありません。

ということで、辞書を活用して単語の意味から自動で込められた上辺の感情を読み取ろう、というのを、今回Pythonで進めていきます。勿論、人工知能ではありません。

Pythonのインストールまでは割愛です。こちら(http://oita.oika.me/2018/05/03/python3-mecab-on-windows/)を参考にして必要なものをどんどんインストールしておきましょう。

概要

ML-Askというものを利用して、感情表現辞典を元に文字列の含まれる感情表現を抽出、評価します。

ML-AskにはMeCabが必要だそうなので、

MeCabのインストール ② 辞書をNEologd辞書に変更 ③ ML-Askのインストール

の手順で進みます。

また、ここではWindows10 64bit環境で進めていきます。

MeCabのインストール

Pythonは64bitなのでここからダウンロードして、64bit版をインストール。これはページにも書いてありますが公式ビルドのものではありません。ただ、出来るだけ簡単に導入したいのでこれを使います。

問題点は辞書がUTF-8なのでコマンドプロンプトなどから利用する場合に文字化けしまくります。ほかの用途で使うなら向かないかも???

注)32bit版のPythonを使用しているなら公式からダウンロードして利用出来ます。

実行して、そのままインストールしていきます。特にバンドルウェアなどはなさそう(多分)。

インストールできたら、 C:\Program Files\MeCab\bin にPATHを通す。

上手くいかない場合は、C:\Program Files\MeCab\binにある実行ファイルを直接指定しても実行自体は可能。

あと、再起動をかければどうにかなる。

最低限の動作チェック

環境変数の登録が上手くいかなくても、直接実行ファイルを叩いてあげれば動いているかどうかはチェックできる。 文字コード的な問題で文字化けするのでその辺はいったん気にしないでおこう。

Python のMeCabラッパーをインストールする。

ここからが本命。mecab-python-windowsというPythonのラッパーをインストールする。これでPythonからMeCabを操作できるようになる。

インストールはpipから実行すればよい。仮想環境の切り替えなどは適宜行えばよいので割愛。

  pip install mecab-python-windows

すんなり入った。

そのままipythonで動作チェックしてみる。

  import MeCab
m = MeCab.Tagger("-Ochasen")
print(m.parse("すもももももももものうち"))

問題無く動作することを確認。例文も参考元からそのままだね。

NEologd 辞書を導入

標準の辞書の制度がそこまでよくないらしい。そのため、精度をよくするために別の辞書であるNEologd辞書を導入しておく。

この部分は実はいらない、ここから少し面倒になるので割愛してよい。

NEologd辞書のビルドがLinux環境でしかできないらしい。ここで、Linux機を導入するのも面倒なので、Linux環境がない人はWindows Subsystem for Linux(WSL)を使用する必要がある。なので、まずはWSLのUbuntuをインストールしていきます。

参考: https://qiita.com/ChenZheChina/items/42f1fcc763e88cb02cca

まずはWSLの使用許可

これは管理者権限ありのPowerShellで以下のコマンドを実行すればよい。

  Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux

ちなみに、アイコンを右クリックすれば「管理者権限で実行」が出てくる。

以下のような画面が出てくるので少し待つ。

すると再起動を求められるので、ここで再起動。

WSL用のUbuntuをインストール

導入自体は簡単。Microsoft Storeでインストールする。「Ubuntu」って検索すれば出てくる。

容量もそんなに食いません。容量が足りない場合は適当に要らないものを消すか、…というかそんなに容量が足りない状態でPC使うなよ(笑)って感じですな。ストレージの交換かディスクのクリーンアップでもしておきましょう。

インストールが終わればポップアップが出てきます。

インストールが終われば起動します。普通にスタートメニューに登録されます。

初回起動時はUbuntuのシステムのインストールから始まるようです。少し待ちましょう。

まずはユーザーネームとパスワードを設定します。これが終わればubuntuを利用できるようになります。これらのユーザーネームとパスワードは任意のものでよいです。

WSLのUbuntuでのインストールの下準備

実は、ビルドの準備はまだ終わらないんだ。とはいえ、以下の手順でやっていけば恐らく正常にインストールできるはず。時間がちょっとかかるけどね。以下はWSLのUbuntuのターミナル内での作業。

まずはaptのアップデートとupgradeをかませておく。

  sudo apt update
sudo apt upgrade

この辺りでいきなりエラーが出まくるので、恐らく、リポジトリを日本サーバーに変更することで解決される?? 以下を実行することで僕の環境では解決した。その後、aptのアップデートなどを再度試してエラーが出ないことを確認。https://qiita.com/Aruneko/items/c79810b0b015bebf30bb

  sudo sed -i -e 's%http://.*.ubuntu.com%http://ftp.jaist.ac.jp/pub/Linux%g' /etc/apt/sources.list

後のNEologdのビルドでエラーが出るのを避けるため、build-essentialを再インストールしておく。ビルド時にmake is not found.というエラーが出た場合、「build-essential」の再インストールが必要だそうだ。というか何もせず進めたら出た。http://zaka-think.com/linux/ubuntu/ubuntu-make-error/

  sudo apt install --reinstall build-essential

ただ、上の日本サーバーに切り替えをしておかないとここで躓くのでやっておこう。

gitをインストールする必要があるので、以下でインストール。

  sudo apt-get install git

gitと入力すると、各種コマンドについての説明が出てるので恐らく問題ない?

  git

また、gitの初期設定も行う…ってのはいらなかった。逆に、GitHubにいってアカウントを作っておこう。これはググってwebサイトに行ってね。

  git config global user.name [任意のユーザ名]
git config global user.email [任意のユーザ名]

NEologd辞書のビルドとmecab関連のインストール

gitがインストールできたので、mecab関連をインストールしていきます。この手順が不要かどうかは試していない…。まあ、入れておきましょう。

  sudo apt install mecab
sudo apt install libmecab-dev
sudo apt install mecab-ipadic-utf8

次に、gitを用いてNEologd辞書をインストールしていきます。この時にgithubのユーザーネームとパスワードが必要になります。入力して問題がなければ、インストールされる容量が結構あるのでじっくりと待ちましょう。約350MBです。

回線速度というか、よくわからない何かがボトルネックになっているかと。1Mbpsは出ていなかった…。

  git clone https://github.com/neologd/mecab-ipadic-neologd.git

ダウンロードが済んだら、移動してビルドしましょう。上記手順をすべてこなしていれば恐らく正常にインストールできるはず。僕は上記手順のみでできた。

  cd mecab-ipadic-neologd
sudo bin/install-mecab-ipadic-neologd

NEologd辞書をWindows側の移す

ビルドされた辞書をWindows側に移していきます。

Ubuntu側のNEologd辞書は/usr/lib/mecab/dic/mecab-ipadic-neologd/にある…?\usr\lib\x86_64-linux-gnu\mecab\dicじゃね? 僕の環境では後者の場所にありました。

これをWindows側のC:\Program Files\MeCab\dic\ipadic-neologd\にコピーすればよい。こんな感じ?まあ、多分フォルダ名まで変更する必要はなかったかと。

注) コピーについて

多分、WSLのUbuntu側から操作してコピーできるかもしれないけど、面倒なので直接取りに行く。

Ubuntuのフォルダは、%LOCALAPPDATA%\Packages\内にある。Windows側のエクスプローラーに直接入れて叩けば飛んでくれる。

その中から、CanonicalGroupLimited.UbuntuonWindows_[謎の文字列]というフォルダを見つけて、「LocalState」→「tootfs」と順に移動していけばUbuntu内のファイルにアクセスできる。

「mecab-ipadic-neologd」フォルダの場所の例は以下。[ユーザー名]と[謎の文字列]はたぶん人によって違う。

C:\Users\[ユーザー名]\AppData\Local\Packages\CanonicalGroupLimited.UbuntuonWindows_[謎の文字列]\LocalState\rootfs\usr\lib\x86_64-linux-gnu\mecab\dic\mecab-ipadic-neologd\

参考: https://qiita.com/keita44_f4/items/4fffda7048b2c3554f14

mecabが指定している辞書の位置を変更する

最後に、C:\Program Files\MeCab\etc\mecabrc (拡張子無しのファイルだよ)をテキストエディタで開いて、6行目のdicdir = $(rcpath)\..\dic\ipadic

  dicdir =  $(rcpath)\..\dic\ipadic-neologd

に書き換えます。

注意事項として、テキストエディタ側に管理者権限がないとこのファイルは書き換えができないので要注意。

動作チェック

再度、以下で確かめてみる。

  import MeCab
m = MeCab.Tagger("-Ochasen")
print(m.parse("すもももももももものうち"))

????

微妙?もっと長い文章で試しておいた方がいいかもね。

WSLでのコピペ

注意、WSLの画面にコマンドをコピペするにはCtrl+Vでは(多分)できません。ただ、左上のアイコンをクリックするとメニューが出てくるので、ここから貼り付けます。

ML-Askを導入

これでようやく感情分析に入ることが出来ます。以下を参考にしてML-Askを導入していきましょう。

参考: https://qiita.com/yukinoi/items/ef6fb48b5e3694e9659c?utm_source=stock_summary_mail&utm_medium=email&utm_term=kwtsh365&utm_content=ML-Ask%E3%81%A7%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88%E3%81%AE%E6%84%9F%E6%83%85%E5%88%86%E6%9E%90&utm_campaign=stock_summary_mail_2018-12-29

インストール

以下からインストール

  pip install pymlask

問題無くインストールできた。

動作確認

  from mlask import MLAsk
emotion_analyzer = MLAsk()
emotion_analyzer.analyze('彼のことは嫌いではない!(;´Д`)')

最低限動いてくれているようだ。ぱちぱち。おめでとう。

今回出来るようになったことのまとめ

出来るようになったのは形態素解析と感情分析

  import MeCab
from mlask import MLAsk

string="近年では、親愛の情を込めて友人、知人や親族にも贈るお歳暮へと少しずつ変化してきているようです。"

m = MeCab.Tagger("-Ochasen")
print(m.parse(string)

emotion_analyzer = MLAsk()
emotion_analyzer.analyze(string)

結果はこんな感じ。

最後に

これで、形態素解析+感情分析が一応出来るようになりました。ここから、ML-Askの使い方を学んでいけば、最低限の感情分析を出来るようになるかと。

適当にモジュールを使って、何かしらのパラメーターを取り出して言えたらいいなー、って感じだね。

まあ、人工知能的なものではないので、辞書をカスタムしないと精度はよくならないので、この辺はGoogleとかIBMとかMicrosoftとかの感情分析の方がちゃんとパラメーターを取り出せるんだろうけどね。

こっちの方がお金はかからないのでいいね。

それでは、クロガネでした。

termcolorでPythonのprint文に色を付けよう!

こんにちは、鉄火巻です。

プログラムを作っていて、結果の表示やデバック用にprint()をよく利用しています。

しかし、コマンドプロンプトの真っ黒な画面に白文字のみ表示されているため、なんとなくおもしろみがありません。
とはいえ、コマンドプロンプト自体の色やフォントの色を変えるもの違うし…

、と探していたらちょうどいいモジュールを見つけました!

termcolorというモジュールをインストールすると、出力に色を付けることが出来るようです!
pypi: https://pypi.org/project/termcolor/

termcolorの導入

というわけで、さっそく導入していきましょう!

「termcolor」というモジュールをpipからインストールします。

  pip install termcolor

以上でOKです!簡単だね。

Let’s 試用!

ipython上で確認していきましょう。

使い方は、文字列の入った変数に色付けをして新しい変数に入れる、といった感じですかね?

  import termcolor
print(termcolor.colored("a","red"))

以下のようにしても問題なく使えます。こっちの方が短くていいね。

  from termcolor import colored
print(colored("ai", "red"))

すると以下のように色が付く。

これで装飾できました。ぱちぱち。

….

と思ったけど、プログラムに意気揚々と組み込むと上手くいきません。

Windows向けの解決策

どうやらWindowsでは「colorama」というモジュールもインストールする必要があるようです。

参考: https://stackoverflow.com/questions/21858567/why-does-termcolor-output-control-characters-instead-of-colored-text-in-the-wind

読んでみたところ、文字コードの問題CP932ちゃんは自己主張がつよいですね~。

以下のように「colorama」というモジュールを追加でインストールします。

  pip install colorama

また、coloramaを初期化する必要があるので、import辺りに同時に突っ込んでおきましょう。多分、初期化さえされていればどこもよいのでしょう?

  from termcolor import colored, cprint
import colorama
colorama.init()
cprint("aa", "red")

ipythonでなくともちゃんと色付けされて出力出来ることが確認できました!

おめでとう。

大まかな色付けの仕方

色付けの仕方には、cprint()と、colored()の2通りがあります。

基本的に使い方は一緒で、「 cprint() = print() + colored() 」なだけですね。

文字列の一部や、変数に入れた文字列を色付けするときにcolored()の方を使えばいいってかんじですかね?

  cprint("{string}", "{text colors}", "{text highkights}", attrs=["{attributes}"])

例:

※エラー文的にも、「 cprint() = print() + colored() 」はあっているみたいですね。適当にエラーを吐かせると、以下のように表示されます。

  print((colored(text, color, on_color, attrs)), **kwargs)

使える色

色のリストは上記pypiのページにあります。上記から引用。
詳細は上記pypiに行きましょう。

Text colors:

grey

red

green

yellow

blue

magenta

cyan

white

Text highlights:

on_grey

on_red

on_green

on_yellow

on_blue

on_magenta

on_cyan

on_white

Attributes:

bold

dark

underline

blink

reverse

concealed

※attributesはwindows環境ではreverseしか利用できないことに注意。どのattributeがどの環境で利用できるかは、上記pypiのサイトに書いてあります。

上でやったけど、reverseも効いてなくね?謎だね。

一部を色付け

以下のようにしたら一部を無理やり色付けできる。多分簡単な方法はあると思うけど、正直これで問題無く使用できます。

  print(colored("[loop{0}]: ".format(self.looptimes), "red"),"Finish load lib")

まとめ

今回はコマンドプロンプトに色を付けることが出来るようになる「termcolor」を紹介しました。うまく使えば結果の視認性も上昇かもしれないですね。

ただし、Windowsユーザーの方は一緒に「colorama」も導入する必要があるので注意が必要です。若干冗長的になります。


以上です。これで味気のないコマンドプロンプトの画面を煌びやかにすることが出来るようになりました!おめでとう!

ただ、毎回、importするたびに初期化も書いてあげないといけないのが難点ですね。

とはいえ、装飾したほうが他人に渡すときは見やすくていいかもね。
もちろん、配色にもよると思うけど。

それでは、鉄火巻きでした。

Notepad++から直接Pythonを実行しよう!


こんにちは、鉄火巻です。

Notepad++は個人的にとても気に入っているエディタです。
かなり軽量で便利です。今時少ないメモリ2GBのWindows10機でももたつくことなく動かすことが出来るので貴重なエディタです。

エディタはいろいろあるのでNotepad++が一概にいいわけではありません。
知り合いにGENIEをすすめ勧められたこともあります。F5で保存&実行が可能なのはとても便利に思いました。
ちょっと揺らいだんですけど、Notepad++で関数名や変数を選択すると全部ハイライトしてくれるのはとても便利で捨てられない要素です。

というわけで、そういったNotepad++の弱点を塞いでいきましょう。
Notepad++から、直接Pythonを実行できるように設定します。

と思ったんですが以外にドキュメントがありません。

幸い、転用可能に思われるドキュメントはいくつかあったことと、知り合いの助けがあって実行できるようになりました。ということで共有していこうと思います。

概要

Notepad++には「ファイル名を指定して実行」という機能があります。この機能を利用して
仮想環境も利用できる応用的な手法です。

batファイルを作る

いきなりコードを掲載します。適宜、ファイル名を書き換えて使用してください。僕は「npp_python.bat」で登録しました。「Python.bat」や「cmd.bat」はよくないといううわさを聞いたことがあるので避けた方が賢明なようです。

@echo off
python %~f1
pause

また、venvの仮想環境を設定したい場合は以下のように指定しましょう。仮想環境を呼び出すときと同じ手順です。

@echo off
call c:\work\pywork\envs\expenv\Scripts\activate.bat
python %~f1
call deactivate
pause

また、個人的に、「pause」部分を以下のように変更すると便利です。

timeout 10

プログラムの終了後の10秒後、もしくは何かのキーを押すと自動でコマンドプロンプトの画面が閉じられます。開きっぱなしになることを防ぐことが出来ます。まあ、毎回閉じればいいんですがね…。

ともあれ、エラーコードを読むにしても30秒くらいに設定しておけば問題ないとは思います。

.batファイルをNotepad++から呼び出す

次にNotepad++側の設定をしていきましょう。
「設定(R)」→「ファイル名を指定して実行(F5)」に以下を記入します。

(.batファイルのディレクトリ) "$(FULL_CURRENT_PATH)"

入力したらこんな感じ。

「(.batファイルのディレクトリ)」部分は、「c:\work\npp_python.bat」のように、上記.batファイルのディレクトリを指定します。例えば、「c:\work\」に先ほど作成した.batファイルがある場合は以下のようになります。

c:\work\npp_python.bat "$(FULL_CURRENT_PATH)"

また、「”$(FULL_CURRENT_PATH)”」との間に半角スペースが必要です。

このまま実行してみて問題無く実行されることを確かめましょう。

問題無く実行されたら、先ほどの「ファイル名を指定して実行(F5)」のウィンドウを再度開き、ショートカットキーに設定しておきましょう。
下図の赤枠部分をクリックして、

僕は以下のように「Ctrl+F5」に登録しました。ショートカットキーは競合しなければどのように設定しても問題ないので、お好みで。既定のショートカットキーも変更できるので不要なものを削除してから登録してみてもいいかもしれません。
また、「Python」などのように何のショートカットキーなのかが分かりやすい名前も登録しておきましょう。

そうすれば、次回以降は「Ctrl+F5」を押すことで、開いているPythonのコードをNotepad++から直接実行することができるようになります。

ぱちぱち。

仕組みについて

これでめでたく実行できるようになりました。ただ、投げっぱなしもよくないので、可能な範囲で解説していきます。

Notepad++の設定

まず、Notepad++側の設定から。簡潔に言えば、Notepad++で開いているファイルのフルパスを.batファイルに渡します。

(.batファイルのディレクトリ) "$(FULL_CURRENT_PATH)"

「ファイル名を指定して実行(F5)」は名前の通り、ファイル名を指定して実行することが可能です。なので、関連付けさえされていれば何でも実行させることが出来ます。勿論.exeファイルも実行できます。

「”$(FULL_CURRENT_PATH)”」部分は、Notepad++の「ファイル名を指定して実行(F5)」のウィンドウを開いたときに使用していたタブのフルパスが入るようです。

例えば、「helloworld.py」をNotepad++で開いていた場合、「”$(FULL_CURRENT_PATH)”」部分に「helloworld.pyのフルパス」が入ることになります。「helloworld.py」を「c:\work\」に保存していた場合、「c:\work\helloworld.py」が渡されていることになります。

また、この時、”$(FULL_CURRENT_PATH)”が、作成した.batファイルの第1引数に渡されることになります。

.batファイルの仕組み

基本的に、ただの.batファイルです。詳しい方は何でもできます。
以下を解説していきましょう。

@echo off
python %~f1
pause

といっても、説明する部分は「python %~f1」位しかありません。これも.batファイルでは普通のことですが、ほかは普遍的すぎるので省略します。

「python %~f1」は、普段、「python helloworld.py」とかやって.pyファイルを開くことと同じです。

ミソは「%~f1」部分です。これは、「第1引数をファイル位置として受ける」という意味です。

もともと、「%1」で第1引数の入る場所を指定できます。例えば、「~.bat aaa」として、「echo %1」としておけばコマンドプロンプトの画面に「aaa」と表示されるはずです。

ただし、「%1」のままでは文字列として扱われ、ファイル位置として扱われません。少なくとも、僕の環境では「%1」のままではPythonのコードをNotepad++で実行できませんでした。

ここを「%~f1」とすると、第1引数をファイル位置として扱ってくれます。

前述のように、Notepad++の「ファイル名を指定して実行(F5)」で.batファイルに「”$(FULL_CURRENT_PATH)”」を第1引数として渡しているので、この.batの第1引数に開いているファイルのフルパスが渡されます。

例えば、先ほどの例だと、2行目部分が「python c:\work\helloworld.py」と同じになります。これで、問題なく実行できるようになります。

まとめ

どうでしたか?実行できるようになりましたか?
まあ、プラグインで一発で解決するらしいですけどね。
とはいえ、ここに書いてある内容をコピペすれば問題なく実行できるようになるはずです。

ただし、GENIEのように「保存&実行」が出来ているわけではありません。
そのあたりは、適宜「Ctrl+s」を押してから「Ctrl+F5」を押しましょう。押すボタンが1つ増えるだけです。
逆に保存しないと変更前のファイルが実行されるので要注意です。

これで便利なNotepad++が一層便利になりました。
個人的にとても気に入っているので今後もNotepad++民として使い続けたいですね。

それでは、鉄火巻でした。

Android端末上でもPython3を動かすことが出来る「Pydroid 3」

こんにちは、鉄火巻です。

Pythonの勉強をちょっとだけやっています。
ただ、開発環境がPCに限られているので、家でしか実行できないという部分が問題でした。

そこで見つけたのがPyroid 3です。

play.google.com

「Pydroid 3」で何が出来るのか

これはオフラインで動くPython 3.6にIDEのようです。
僕自身が把握できている特徴としては、

といったところでしょうか。

端的にまとめると、僕程度の素人であれば大抵のことは出来ると思われます。

インストール

GooglePlayで「pydroid」と検索すれば「Pydroid 3 – Educational IDE for Python 3」というアプリが出てきます。
play.google.com

普通にインストールします。
f:id:kurogane-games:20180926001731p:plain
容量は41.85MBでした。意外と軽量。

Android 4.4以上に対応しているので、それより古い端末では利用できません。
とはいえ、4.4 KitKatはリリース日が2013年10月31日なので、今時の端末であればそもそも気にする必要はないでしょう。
古い端末を再利用するときだけ気を付けてください。

ちなみにアイコンはこんな感じ。
f:id:kurogane-games:20180926002316p:plain

起動するとインストールが始まります。
しばらく待ちましょう。
f:id:kurogane-games:20180926002530p:plain

また、C++IDEをインストールしてみてね、って出てきます。
f:id:kurogane-games:20180926002516p:plain
多分、インストールはしなくてもいいと思われます。

インストールが終わればIDEの画面が姿を現します。
普通のエディタとおおよそ同じですね。
f:id:kurogane-games:20180926002636p:plain

Hello World“してみる

まずは”Hello World“をしてみましょう。
単純に、

print("Hello world")

で実行します。

実行するときは右下の黄色の再生ボタン(▶)を押しましょう。
実行すると、コンソール画面に切り替わります。
ちゃんとprint()文が働いてくれていますね。
f:id:kurogane-games:20180926003003p:plain

今回はこの辺で。
次回はpipを使ったパッケージのインストール、外部ファイルの読み込みなどを試してみたいと思います。

それでは、鉄火巻でした。

python-pptxインストール直後にエラーが出たときの対処法

こんにちは、鉄火巻です。

 

今回はプログラミング系の記事。

python-pptxインストール直後にエラーが出たときの対策を書こうとと思います。

概要

 PythonからPowerPointファイルを生成しようとしたらいきなりエラーを吐きました。

まずはインストール 

pip install python-pptx

次に下のGetting Startedの「Hello World! example」の実行でエラーがいきなり出ました。
Getting Started — python-pptx 0.6.13 documentation

エラー1「lxmlモジュール」

ImportError: cannot import name 'etree' from 'lxml'

これは以下を実行したら改善(?)した。

pip install lxml -U

バージョンとかの問題だったのかな?

エラー2つ目「Pillowモジュール」

上記の「lxml」モジュールの問題が解決したら次に以下の問題が出た。

ImportError: No module named Image

同じくアップグレードをかけても解決しなかったので、再インストールを試みたら問題無くGetting Startedの「Hello World! example」が実行できた。

pip uninstall Pillow
pip install Pillow

これは何が問題だったのかは不明。
少なくとも、Python自体を再インストールしたら改善した、ってのをweb上で見つけたので、代わりにモジュールを再インストールしてみたらうまくいった。

これで問題無くPythonからPowerPointファイルを生成できるようになりました。

ぱちぱち。

それでは、鉄火巻でした。