[PyCharm]Optimize importsで必要なimportが消えてしまう時に読むページ
概要
PycharmやIntelliJなどのJetBrainsのIDEでは、2021.2から、保存時のアクションで、オートフォーマットができるようになりました
それまでは別のプラグインが必要だったので、大変助かりますね
さて、その中のOptimize imports
に関して
例えばJavaであれば使用されていないimportがなくなることは困らないのですが、Pythonの場合は、言語の特性上、importだけで使用・適用を行う場面が存在します。
すると、Optimize imports
は、ソースコード内で使用されないimportを自動で消してしまいます。
この対策について、本記事を残しておきます。
Optimize importsから除外する対策
一つは、以下のように、対象のimportの前に# noinspection PyUnresolvedReferences
を付与します
# noinspection PyUnresolvedReferences import os
これでOptimize import
をかけても、そのimportは守られます。
Optimize importsを無効にする対策
そもそも設定から無効にするには、
冒頭で挙げたActions on Save
派の方は、Tools > Actions on Save
よりチェックを外すことで
Ctrl+Alt+L(Mac: Command+Option+L)
の手動フォーマット派の方は、Ctrl+Alt+Shift+L(Mac: Command+Option+Shift+L)
から表示されるダイアログより、外すことができます
参考
python - Make IDE/linter ignore a seemingly unused import - Stack Overflow
[Git].gitignoreで無視したディレクトリの中のサブディレクトリを追跡する
.gitignoreで無視したディレクトリの中のサブディレクトリを追跡する
以下のようなファイル構造の時に、directory
を無視しつつ、subdirectory
だけを追跡したいと考えます。
│ .gitignore │ └─directory │ not-important.txt │ └─subdirectory important.txt
.gitignoreに以下のように書くと、うまくいきません。
これは、 ディレクトリを無視する構文(/directory/
)を使用すると、それ以下のファイルは常に無視をされる ためです
/directory/ !/directory/subdirectory
そのため、 ディレクトリの無視ではなく、ファイルのワイルドカードでの無視 を使用します。
ファイル単位で無視 -> ディレクトリを追跡 という手順を踏むと、うまくいきます。
# ファイル単位で無視 /directory/* # ディレクトリを追跡 !/directory/subdirectory/
git add .
, git status
を叩くと、追加されていることが確認できます
>git add . >git status On branch master Changes to be committed: (use "git restore --staged <file>..." to unstage) modified: .gitignore new file: directory/subdirectory/important.txt
さらに前の行にて無視されているとき
さらに前の行にて/directory
が無視されているときは、ファイル単位で無視 -> ディレクトリを追跡 を繰り返し行います
# ファイル単位で無視 /* # ディレクトリを追跡 !/directory/ # ファイル単位で無視 /directory/* # ディレクトリを追跡 !/directory/subdirectory/
参考
git - .gitignore exclude folder but include specific subfolder - Stack Overflow
[Docker]使い捨てのMySQLをサクっと作る方法
Dockerにて使い捨てのMySQLをサクっと作る方法
次のコマンドにて、サクっと作って検証できます。
コンテナ起動
>docker run --rm --name mysql -e MYSQL_DATABASE=mydb -e MYSQL_ROOT_PASSWORD=root-password -d mysql:latest
接続
>docker exec -it mysql /usr/bin/mysql -uroot -proot-password mydb
コンテナ終了
>docker stop mysql
参考
[SQL]WHERE ~ IN句を複数条件(タプル)にて指定する方法は?
WHERE ~ IN句を複数条件(タプル)にて指定する方法
以下のテーブルを考えます
mysql> CREATE TABLE fruits (
-> category_1 int,
-> category_2 int,
-> fruit varchar(10)
-> );
Query OK, 0 rows affected (0.06 sec)
mysql> INSERT INTO fruits VALUES
-> (1, 1, "apple"),
-> (1, 2, "banana"),
-> (2, 1, "kiwi"),
-> (2, 2, "orange");
Query OK, 4 rows affected (0.01 sec)
mysql> SELECT * FROM fruits;
+------------+------------+--------+
| category_1 | category_2 | fruit |
+------------+------------+--------+
| 1 | 1 | apple |
| 1 | 2 | banana |
| 2 | 1 | kiwi |
| 2 | 2 | orange |
+------------+------------+--------+
4 rows in set (0.00 sec)
ここで、(category_1, category_2)
が(1, 1)
か(2, 2)
のものを取得したいと考えます。
ANDとORを使用しても書けるのですが……、
SELECT fruit FROM fruits WHERE (category_1 = 1 AND category_2 = 1) OR (category_1 = 2 AND category_2 = 2);
以下のようにIN
を使うことで、スマートに書くことが可能です。
SELECT fruit FROM fruits WHERE (category_1, category_2) IN ((1, 1), (2, 2));
PostgreSQL, DB2に関しては、VALUES
が必要のようです
SELECT fruit FROM fruits WHERE (category_1, category_2) IN (VALUES (1, 1), (2, 2));
参考
mysql - selecting where two columns are in a set - Database Administrators Stack Exchange
[Gradle]タスクの依存関係を表示する
きっかけ
Mavenではビルドライフサイクルの中で、決められた一連のタスクが頭から流れるため、なんとなく覚えていれば「この操作の前に処理を挟みたければあのタスクだな。」等がぱっとわかると思います。
Gradleだと、タスクの自由度の高さがある一方「このタスクってどういう順で実行されるんだけ?そもそもなんでこの順になるんだっけ?」となることがあります(筆者はなりました)。
そこで、Gradleでタスクの依存関係を確認する方法を調査しました。
タスクが実行される順序を確認する
gradle <タスク名> --dry-run
を使用することで、どの順で何のタスクが実行されるかを表示することができます。
>./gradlew build --dry-run :compileJava SKIPPED :processResources SKIPPED :classes SKIPPED :jar SKIPPED :startScripts SKIPPED :distTar SKIPPED :distZip SKIPPED :assemble SKIPPED :compileTestJava SKIPPED :processTestResources SKIPPED :testClasses SKIPPED :test SKIPPED :check SKIPPED :build SKIPPED BUILD SUCCESSFUL in 1s
タスクの依存関係を確認する
gradle-taskinfo
プラグインを使用します
build.gradle
に、以下のように追加します
plugins { id 'org.barfuin.gradle.taskinfo' version '2.0.0' }
gradle tiTree <タスク名>
にて、treeが表示されます。
>./gradlew tiTree assemble > Task :tiTree :assemble (org.gradle.api.DefaultTask) +--- :distTar (org.gradle.api.tasks.bundling.Tar) | +--- :jar (org.gradle.api.tasks.bundling.Jar) | | `--- :classes (org.gradle.api.DefaultTask) | | +--- :compileJava (org.gradle.api.tasks.compile.JavaCompile) | | `--- :processResources (org.gradle.language.jvm.tasks.ProcessResources) | `--- :startScripts (org.gradle.api.tasks.application.CreateStartScripts) | `--- :jar (org.gradle.api.tasks.bundling.Jar) | `--- :classes (org.gradle.api.DefaultTask) | +--- :compileJava (org.gradle.api.tasks.compile.JavaCompile) | `--- :processResources (org.gradle.language.jvm.tasks.ProcessResources) +--- :distZip (org.gradle.api.tasks.bundling.Zip) | +--- :jar (org.gradle.api.tasks.bundling.Jar) | | `--- :classes (org.gradle.api.DefaultTask) | | +--- :compileJava (org.gradle.api.tasks.compile.JavaCompile) | | `--- :processResources (org.gradle.language.jvm.tasks.ProcessResources) | `--- :startScripts (org.gradle.api.tasks.application.CreateStartScripts) | `--- :jar (org.gradle.api.tasks.bundling.Jar) | `--- :classes (org.gradle.api.DefaultTask) | +--- :compileJava (org.gradle.api.tasks.compile.JavaCompile) | `--- :processResources (org.gradle.language.jvm.tasks.ProcessResources) `--- :jar (org.gradle.api.tasks.bundling.Jar) `--- :classes (org.gradle.api.DefaultTask) +--- :compileJava (org.gradle.api.tasks.compile.JavaCompile) `--- :processResources (org.gradle.language.jvm.tasks.ProcessResources) BUILD SUCCESSFUL in 1s 1 actionable task: 1 executed
gradle tiOrder <タスク名>
にて、タスクの順番も表示可能です。
>./gradlew tiOrder assemble > Task :tiOrder In order to execute [:assemble], the following tasks would be executed in this order: 1. :compileJava (org.gradle.api.tasks.compile.JavaCompile) 2. :processResources (org.gradle.language.jvm.tasks.ProcessResources) 3. :classes (org.gradle.api.DefaultTask) 4. :jar (org.gradle.api.tasks.bundling.Jar) 5. :startScripts (org.gradle.api.tasks.application.CreateStartScripts) 6. :distTar (org.gradle.api.tasks.bundling.Tar) 7. :distZip (org.gradle.api.tasks.bundling.Zip) 8. :assemble (org.gradle.api.DefaultTask) BUILD SUCCESSFUL in 1s 1 actionable task: 1 executed
詳しくはリンクより、ドキュメントをご確認ください。
出典
Is there a way to list task dependencies in Gradle? - Stack Overflow
[中野で時計買取]本当に高く売れるのか調査してみた
背景
以前インターネットや雑誌等に影響されて、一般的に「高級時計」される時計を購入しました。
しかし、もともとインドアなのに加えて、感染症の影響により外に出る機会ががくんと減り、また、時計に関する思いも、実際に使ってみたり、在宅の日々を過ごしたりする中で変化したので、思い切って買取に出すことにしました。
一括査定サイトや、フリマアプリなど、いろいろな方法を検討したのですが、今回は時計で有名な中野のお店を巡ってみることにしました。
事前にどこに持っていこうか情報収集をしようと「中野 時計買取」で検索すると、いろいろなお店・口コミが出てくるのですが、「ここは凄くよく書いてあるけどステルスマーケティングでは……?」とか「このお店は、実在庫がないとか買い叩かれたとか、結構悪いことも書かれているな……。」とか、いろいろ読んでいるうちに、不安になってきました。
そこで、実際にいろいろなお店を回って買取査定をした、その備忘録として、本記事を残しておきます。
査定に出したもの・姿勢
詳細な型番は控えますが、スイスの時計メーカーIWC (International Watch Company)の、以下2本になります。
- マークシリーズ(パイロットウォッチ)
- アクアタイマー(ダイバーズウォッチ)
両方とも、箱・保証書がついた状態で、インターネットで中古にて購入しました。
査定員の方から「綺麗ですし精度もいいです。実際に着用されていましたか?」と聞かれる程度には、良い状態の物でした(着用時は気を遣ったり、使い終わったら拭いたりと、大事に使っていました)。
時計を売る温度感を聞かれた際には「本日は冷やかしではなく、一通り回らせて頂いたうえで、一番高いところに時計を置いて帰る。」ということをちゃんと伝えました。
また、回るにつれて、それ以前に回ったお店より安い金額を提示された場合には「他店ではこれくらいの金額を提示されている。」ということを伝えながら回りました。
査定結果
以下査定が出た順となります(単位: 万円/四捨五入あり)。
お店 | マークシリーズ | アクアタイマー | 備考 |
---|---|---|---|
A | 23 | 26 | 「マークシリーズはトップガンシリーズの影響等で人気で、割といい値段と思う。」 「アクアタイマーはうちの店だとちょっと売れ行きが良くなくてこのお値段です。」とのこと |
B | 22 | 27 | |
C | 24 | 29 | |
D | 26 | 24 | 唯一マークシリーズの方が高かったお店。話を聞くと、お店によって得意・不得意な商品があるとのこと マークシリーズはこちらで買取を依頼 |
E | 23.1 | 25.2 | |
F | 23 | 30 | |
G | 23 -> 25 | 29 -> 30 -> 30.5 | 査定金額が出てから、今までの結果を伝えると、それぞれ25万円、30万円にアップした アクアタイマーはこちらで買取を依頼。 最後に戻ってきて買取に出すときに、30.5万円になりませんか?と聞いて、OKをもらった |
H | 21 | 23.6 |
まとめると、以下のようになりました。
時計 | 最高金額 | 最低金額 | 金額差 |
---|---|---|---|
マークシリーズ | 26 | 21 | 5 |
アクアタイマー | 30.5 | 23.6 | 6.9 |
合計 | 56.5 | 44.6 | 11.9 |
感想
まず、最高金額に関しては、インターネットの中古相場等から考えて、予想を超える結果となりました。率直に「高い。結構満足したな。」という気持ちです。
お店ごとの金額の関しては、いろいろ回りながら査定について話を聞いた結果、商品の相場を前提に、お店の得意・不得意により、どうしても差は出るものなのだなと感じました。
合計の最高・最低金額は、金額で言うと20%以上の差がつきました。
時間と体力に余裕があるなら、いろいろ回ってみるのが良いかと思います。
高く売るコツと豆知識
希望金額を聞かれても答えない
査定金額を出す前に「本日はいくらくらいなら置いていって頂けますか?」「他店さんはいくらくらいつけてますか?」と聞かれることがありましたが「まずは是非お値段を出してください。」と、答えない方針にしました。
答えてしまうと、その金額をベースに値付けをされることがあるようです。
最後にもうちょっと上乗せできないか聞いてみる
いろいろ回って、最終的にここに出すぞ!と決め、持って行った段階で「もうちょっと上がりませんか?」と聞いてみるのはどうでしょう。
今回は、マークシリーズの方は電卓を3分くらい叩いたのちに「すみません、限界でした。」とお断りに。
アクアタイマーも同じように聞いたら、すぐに「いろいろ回ったうえで、折角戻ってきてくれたので、OKですよ!」と快諾頂けました。
最後のチャレンジ、ぜひ迷惑にならない程度にしてみてください。
時計1本あたり、査定に10分~15分は見ておく
今回は8店舗回りましたが、時間で言うと4時間ほどかかりました。
私も2店目からは「1店目で動作と精度は問題ないと言われているので、機能は問題ない前提で、外見ベースで値段を出してくれないか。」とお願いしてみたりしましたが、それでもその位かかりました。
時間に余裕を持たせて行くのをお勧めします。
最後に
本記事が、時計を愛する皆様のお役に立てば幸いです。
[Java]Streamを閉じないとリソースリークするよ!っていう話(AutoClosable)
本記事は、JJUGにて登壇したものを、記事向けに加筆修正したものです。
その際の動画・スライドはこちらのページでご覧頂けます。
beppy.hatenablog.com
StreamのAPI仕様確認
StreamのAPI仕様を確認すると、AutoClosableがついています
AutoClosableがついているということは、以下のように、try-with-resources文にて、リソースとして宣言ができます。
(このケースでは、こう書き換えても何もメリットはないのですが……。)
Stream.of(1, 2, 3).forEach(System.out::println); ↓ try (Stream<Integer> stream = Stream.of(1, 2, 3)) { stream.forEach(System.out::println); } > Task :run 1 2 3
AutoClosableが必要となるケース
ではなぜこれが用意されているのかというと、 Readerや、DBのConnection等のリソースを、Stream内部で使用している場合に、使い終わった時にcloseができるようにするため です。
怠ると、リソースやコネクションのリークにつながる可能性があります。
java.nio.file.Files
list
public static Stream
list(Path dir) throws IOException
ディレクトリ内のエントリを要素に持つ遅延設定Streamを返します。 リストは再帰的ではありません。
このメソッドは、 try-with-resources文または類似の制御構造内で使用して、ストリーム操作が完了した後にストリームのオープン・ディレクトリがすぐに閉じられるようにする必要があります。
lines
public static Stream
lines(Path path, Charset cs) throws IOException
ファイル内のすべての行をStreamとして読み取ります。
返されるストリームは、Readerをカプセル化します。 ファイル・システム・リソースのタイムリな破棄が必要な場合は、try-with-resources構文を使用して、ストリーム操作の完了後にストリームのcloseメソッドが呼び出されるようにしてください。
jOOQ(ORM)
ResultQuery
Stream
stream() throws DataAccessException
……
Clients should ensure the Stream is properly closed, e.g. in a try-with-resources statement:
try (Streamstream = query.stream()) {
// Do things with stream
}
close処理を付与したいなら
上記のようなtry-with-resources文で閉じてくれるStreamを自作したい場合、onClose()
を使用することで作成することができます。
S onClose(Runnable closeHandler)
追加のクローズ・ハンドラを含む同等のストリームを返します。
クローズ・ハンドラはストリーム上でclose()メソッドが呼び出されたときに実行されますが、ハンドラの実行順序は追加された順番になります。
いずれかのクローズ・ハンドラから例外がスローされても、すべてのクローズ・ハンドラが実行されます。
……
これは中間操作です。
例えば、以下のようなコードを実行すると、try-with-resource文を抜けたときに、追加された順番でハンドラが実行されていることが確認できます。
Runnable first = () -> System.out.println("first called"); Runnable second = () -> System.out.println("second called"); try (Stream<Integer> stream = Stream.of(1, 2, 3).onClose(first).onClose(second)) { stream.forEach(System.out::println); } > Task :run 1 2 3 first called second called
もっと詳しく知りたい場合、前述したFiles.lines()
の実装が参考になりそうなので、併せてご確認下さい
最後に
恥ずかしながら、私はStreamが閉じれることを知らず、特にjOOQのは見逃す寸前で、危うくコネクションリークを起こすところでした。
改めて、ドキュメントやJavaDocはちゃんと読んで、理解してから使う必要があるなと、反省しました。
それでももし見落としたとしても、本知識があれば「このStreamは外部のリソースを使ってそうだけど大丈夫かな……?」と、注意するきっかけとなると思います。
本記事が、皆様のよいJava Lifeの助けになれば幸いです。
参考・出典
BaseStream (Java SE 17 & JDK 17)
Java8 Stream APIの基本(8) - 終端操作3(close) - エンタープライズギークス (Enterprise Geeks)