gensimの読み込みで実行時エラーが発生する
意外と日本語で検索にヒットしないのでメモ。
発生したエラーはこんな感じ
>>> from gensim.models import word2vec Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/usr/local/lib/python3.7/site-packages/gensim/__init__.py", line 5, in <module> from gensim import parsing, corpora, matutils, interfaces, models, similarities, summarization, utils # noqa:F401 File "/usr/local/lib/python3.7/site-packages/gensim/corpora/__init__.py", line 6, in <module> from .indexedcorpus import IndexedCorpus # noqa:F401 must appear before the other classes File "/usr/local/lib/python3.7/site-packages/gensim/corpora/indexedcorpus.py", line 15, in <module> from gensim import interfaces, utils File "/usr/local/lib/python3.7/site-packages/gensim/interfaces.py", line 21, in <module> from gensim import utils, matutils File "/usr/local/lib/python3.7/site-packages/gensim/matutils.py", line 1076, in <module> from gensim._matutils import logsumexp, mean_absolute_difference, dirichlet_expectation File "__init__.pxd", line 872, in init gensim._matutils ValueError: numpy.ufunc has the wrong size, try recompiling. Expected 192, got 216 >>>
インストールされているバージョンは 3.6.0
$ pip show gensim Name: gensim Version: 3.6.0 Summary: Python framework for fast Vector Space Modelling Home-page: http://radimrehurek.com/gensim Author: Radim Rehurek Author-email: me@radimrehurek.com License: LGPLv2.1 Location: /usr/local/lib/python3.7/site-packages Requires: scipy, numpy, six, smart-open Required-by:
バージョンを一個前(3.5.0
)に戻したらエラーが消えた
$ pip install gensim==3.5.0
そもそも他の人でも起きているのか謎い。。 ただ、Docker環境を作って検証したけど発生したのできっと他にも困っている人がいるはず!
MySQLのインデックスは1つのテーブルにつき1つしか使われないとは限らない
タイトルが全てですが、その通り。 MySQLにはインデックスマージというものが存在するということを最近知った。
詳細は以下のドキュメントを参照してほしい。
MySQL :: MySQL 5.6 リファレンスマニュアル :: 8.2.1.4 インデックスマージの最適化
必ずしも使われるわけではないけど、1つのテーブルにつきインデックスは1つしか使われないものと思っていた認識が誤りだった。
create table user( id int, last_name varchar(20), first_name varchar(20), nickname varchar(20) ) ENGINE = InnoDB DEFAULT CHARSET = utf8;
こんな感じのテーブルがあるとしてインデックスを貼ります。
CREATE INDEX idx_first_name ON user(first_name); CREATE INDEX idx_last_name ON user(last_name); CREATE INDEX idx_nickname ON user(nickname);
データを何件か入れて以下のSQLを実行して実行計画を取得する。
explain select * from user where first_name like 'テスト%' or last_name like 'テスト%' or nickname like 'テスト%';
インデックスを貼っていない場合
+------+-------------+-------+------+---------------+------+---------+------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +------+-------------+-------+------+---------------+------+---------+------+------+-------------+ | 1 | SIMPLE | user | ALL | NULL | NULL | NULL | NULL | 200 | Using where | +------+-------------+-------+------+---------------+------+---------+------+------+-------------+
インデックスを貼っている場合
+------+-------------+-------+-------------+-------------------------------------------+-------------------------------------------+----------+------+------+--------------------------------------------------------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +------+-------------+-------+-------------+-------------------------------------------+-------------------------------------------+----------+------+------+--------------------------------------------------------------------------+ | 1 | SIMPLE | user | index_merge | idx_first_name,idx_last_name,idx_nickname | idx_first_name,idx_last_name,idx_nickname | 63,63,63 | NULL | 3 | Using sort_union(idx_first_name,idx_last_name,idx_nickname); Using where | +------+-------------+-------+-------------+-------------------------------------------+-------------------------------------------+----------+------+------+--------------------------------------------------------------------------+
では、複合インデックスだとどうなるか?既存のインデックスを消して以下のインデックスを追加し、確認する
CREATE INDEX idx_multi ON user(first_name, last_name, nickname);
+------+-------------+-------+------+---------------+------+---------+------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +------+-------------+-------+------+---------------+------+---------+------+------+-------------+ | 1 | SIMPLE | user | ALL | idx_multi | NULL | NULL | NULL | 200 | Using where | +------+-------------+-------+------+---------------+------+---------+------+------+-------------+
なるほど。or
で検索する場合は、複合インデックスを使っても使われることはなく1つ1つのカラムに対してインデックスを貼ることでインデックスマージが効いてパフォーマンスが上がる可能性が高いということらしい。
今回のケースでは Using sort_union
が使われているが公式ページを見ると他にも種類があるようです。
今回の機能はMySQL5以降は有効とのことでMariaDBとMySQL両方で試してみました。こうゆうとき、dockerとか便利ですよね〜と言いたいとこだったけど最新版のMariaDBでエラーが発生して時間かかった。結局バージョンを10.0
まで落とすことで解決したけど。
docker-compose.yml
version: '2' services: maria: image: mariadb:10.0 restart: always volumes: - ./data/mariadb/:/var/lib/mysql ports: - "3307:3306" expose: - "3307" environment: MYSQL_ROOT_PASSWORD: root user: "1000:50" mysql: image: mysql restart: always volumes: - ./data/mysql:/var/lib/mysql ports: - "3308:3306" expose: - "3308" environment: MYSQL_ROOT_PASSWORD: root
mariadb:10.2
で出ていたエラーは以下の通り。時間があったら調べよう
[Warning] InnoDB: Failed to set O_DIRECT on file./ibdata1;OPEN: Invalid argument, ccontinuing anyway. O_DIRECT is known to result in 'Invalid argument' on Linux on tmpfs, see MySQL Bug#26662. [Note] InnoDB: Highest supported file format is Barracuda. [Note] InnoDB: 128 out of 128 rollback segments are active. [Note] InnoDB: Creating shared tablespace for temporary tables [Note] InnoDB: Setting file './ibtmp1' size to 12 MB. Physically writing the file full; Please wait ... [Note] InnoDB: File './ibtmp1' size is now 12 MB. [Note] InnoDB: Waiting for purge to start [Note] InnoDB: 5.7.21 started; log sequence number 1603633 [Note] InnoDB: Loading buffer pool(s) from /var/lib/mysql/ib_buffer_pool [Note] InnoDB: Buffer pool(s) load completed at 180304 4:52:55 [Note] Plugin 'FEEDBACK' is disabled. [ERROR] Could not open mysql.plugin table. Some plugins may be not loaded [Note] Recovering after a crash using tc.log [ERROR] Can't init tc log [ERROR] Aborting
atomで設定を分けて起動する方法
Atom をメインで使っているとソースを書くために使ったりマークダウンエディタとして使ったりします。そのとき、パッケージをまとめて1つの設定に入れても良いんですが、色々な言語のautocomplate系を入れるのが嫌なときやマークダウンエディタとして使いたいときに設定を分けて起動することができます。
ここからはmacをベースにします。
atomの設定は~/.atom
にあります。これを環境変数のATOM_HOME
で指定することで設定を分けることができます。環境変数を指定してatom
コマンドをこんな感じで呼んでやればATOM_HOME
で指定した設定で起動します。
ATOM_HOME=~/.atom_markdown atom
このコマンドを.bash_profile
にエイリアスで登録しておくと捗ります。
alias atommd='ATOM_HOME=~/.atom_markdown atom'
.bash_profile
を読み込んだら以下のコマンドを実行すると~/.atom_markdown
の設定でatomが起動します。
$ atommd .
Eclipse環境での開発サポート
一人で開発している分にはあまり気になりませんが複数人で開発するときに書き方がバラバラだったり、レビューが大変だったりします。コード規約を作っても読まなければならず徹底するのは大変です。 そこで、Eclipseで利用できる開発サポートツールをいくつか紹介します。
まずは、Checkstyleです。これはPleiadesを使っていればバンドルされています。Checkstyleは静的コード解析ツールでルール通りに記載されているかを自動でチェックしてくれるツールです。デフォルトでは、google_checks.xmlが有効になっています。自分好みの設定をすることも可能です。ちなみに僕はタブ区切りでも良いようにルールを変更しています。
FindbugsもPleiadesにバンドルされています。これもCheckstyleと同様、静的コード解析ツールですがこちらはバグになりそうな可能性のあるコードを見つけてくれます。
Eclipse Metrics
あと個人的には、Eclipse Metricsというものを入れています。これは、ソースの複雑度(クラスやメソッドの行数、ネストの深さなど)を計測できるツールです。警告されれば、クラスの責務やメソッドの凝集度などを考える機会になります。 Pleiadesにはバンドルされていなかったので以下のページを参考にインストールしました。
これらを使わなくても開発は可能です。ですが、あった方が保守しやすいコードが書けるかと思います(何ヶ月か前に書いた自分のコードはもはや他人のコードです)。課題としては、設定内容をファイル化してバージョン管理できるようにすれば変更を追跡できて、他の人の環境にも容易に反映することができます。
これらをほぼ網羅でき設定ファイルの共有も楽なRubyGemsのrubocop
は素晴らしいですね。
Spring Bootでoauthのログインセッションをredisに突っ込む
タイトル通りです。 前にoauth認証でのログインができるようにしましたが、これだとログインセッションのあるサーバでしかログイン状態を維持できません。これだとスケールしないので外部に保存します。そこでredisを使ってスケールする仕組みを作りたいと思います。
主に参考にさせてもらったのはこちら。
ただ、oauth認証のコードをベースにしていると以下のようなエラーが出ました。
2017-10-18 21:32:50.838 ERROR 52558 --- [io-8080-exec-10] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception org.springframework.data.redis.serializer.SerializationException: Could not write JSON: Error creating bean with name 'scopedTarget.accessTokenRequest': Scope 'request' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request. (through reference chain: org.springframework.security.oauth2.client.DefaultOAuth2ClientContext["accessTokenRequest"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Error creating bean with name 'scopedTarget.accessTokenRequest': Scope 'request' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request. (through reference chain: org.springframework.security.oauth2.client.DefaultOAuth2ClientContext["accessTokenRequest"]) at org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer.serialize(GenericJackson2JsonRedisSerializer.java:99) ~[spring-data-redis-1.8.7.RELEASE.jar:na] at org.springframework.data.redis.core.AbstractOperations.rawHashValue(AbstractOperations.java:171) ~[spring-data-redis-1.8.7.RELEASE.jar:na] at org.springframework.data.redis.core.DefaultHashOperations.putAll(DefaultHashOperations.java:129) ~[spring-data-redis-1.8.7.RELEASE.jar:na] at org.springframework.data.redis.core.DefaultBoundHashOperations.putAll(DefaultBoundHashOperations.java:86) ~[spring-data-redis-1.8.7.RELEASE.jar:na] at org.springframework.session.data.redis.RedisOperationsSessionRepository$RedisSession.saveDelta(RedisOperationsSessionRepository.java:778) ~[spring-session-1.3.1.RELEASE.jar:na] at org.springframework.session.data.redis.RedisOperationsSessionRepository$RedisSession.access$000(RedisOperationsSessionRepository.java:670) ~[spring-session-1.3.1.RELEASE.jar:na] at org.springframework.session.data.redis.RedisOperationsSessionRepository.save(RedisOperationsSessionRepository.java:388) ~[spring-session-1.3.1.RELEASE.jar:na] at org.springframework.session.data.redis.RedisOperationsSessionRepository.save(RedisOperationsSessionRepository.java:245) ~[spring-session-1.3.1.RELEASE.jar:na] at org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper.commitSession(SessionRepositoryFilter.java:245) ~[spring-session-1.3.1.RELEASE.jar:na] at org.springframework.session.web.http.SessionRepositoryFilter$SessionRepositoryRequestWrapper.access$100(SessionRepositoryFilter.java:217) ~[spring-session-1.3.1.RELEASE.jar:na] at org.springframework.session.web.http.SessionRepositoryFilter.doFilterInternal(SessionRepositoryFilter.java:170) ~[spring-session-1.3.1.RELEASE.jar:na] at org.springframework.session.web.http.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:80) ~[spring-session-1.3.1.RELEASE.jar:na] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.20.jar:8.5.20] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.20.jar:8.5.20] at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197) ~[spring-web-4.3.11.RELEASE.jar:4.3.11.RELEASE] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.11.RELEASE.jar:4.3.11.RELEASE] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.20.jar:8.5.20] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.20.jar:8.5.20] at org.springframework.boot.actuate.autoconfigure.MetricsFilter.doFilterInternal(MetricsFilter.java:106) ~[spring-boot-actuator-1.5.7.RELEASE.jar:1.5.7.RELEASE] at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107) ~[spring-web-4.3.11.RELEASE.jar:4.3.11.RELEASE] at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-8.5.20.jar:8.5.20] at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-8.5.20.jar:8.5.20] at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198) ~[tomcat-embed-core-8.5.20.jar:8.5.20] at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-8.5.20.jar:8.5.20] at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478) [tomcat-embed-core-8.5.20.jar:8.5.20] at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) [tomcat-embed-core-8.5.20.jar:8.5.20] at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:80) [tomcat-embed-core-8.5.20.jar:8.5.20] at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) [tomcat-embed-core-8.5.20.jar:8.5.20] at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342) [tomcat-embed-core-8.5.20.jar:8.5.20] at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:799) [tomcat-embed-core-8.5.20.jar:8.5.20] at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-8.5.20.jar:8.5.20] at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:868) [tomcat-embed-core-8.5.20.jar:8.5.20] at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1457) [tomcat-embed-core-8.5.20.jar:8.5.20] at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.20.jar:8.5.20] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_121] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_121] at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.20.jar:8.5.20] at java.lang.Thread.run(Thread.java:745) [na:1.8.0_121] Caused by: com.fasterxml.jackson.databind.JsonMappingException: Error creating bean with name 'scopedTarget.accessTokenRequest': Scope 'request' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request. (through reference chain: org.springframework.security.oauth2.client.DefaultOAuth2ClientContext["accessTokenRequest"]) at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:388) ~[jackson-databind-2.8.10.jar:2.8.10] at com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:348) ~[jackson-databind-2.8.10.jar:2.8.10] at com.fasterxml.jackson.databind.ser.std.StdSerializer.wrapAndThrow(StdSerializer.java:343) ~[jackson-databind-2.8.10.jar:2.8.10] at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:697) ~[jackson-databind-2.8.10.jar:2.8.10] at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeWithType(BeanSerializerBase.java:580) ~[jackson-databind-2.8.10.jar:2.8.10] at com.fasterxml.jackson.databind.ser.impl.TypeWrappedSerializer.serialize(TypeWrappedSerializer.java:32) ~[jackson-databind-2.8.10.jar:2.8.10] at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:292) ~[jackson-databind-2.8.10.jar:2.8.10] at com.fasterxml.jackson.databind.ObjectMapper._configAndWriteValue(ObjectMapper.java:3697) ~[jackson-databind-2.8.10.jar:2.8.10] at com.fasterxml.jackson.databind.ObjectMapper.writeValueAsBytes(ObjectMapper.java:3097) ~[jackson-databind-2.8.10.jar:2.8.10] at org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer.serialize(GenericJackson2JsonRedisSerializer.java:97) ~[spring-data-redis-1.8.7.RELEASE.jar:na] ... 37 common frames omitted Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'scopedTarget.accessTokenRequest': Scope 'request' is not active for the current thread; consider defining a scoped proxy for this bean if you intend to refer to it from a singleton; nested exception is java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request. at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:355) ~[spring-beans-4.3.11.RELEASE.jar:4.3.11.RELEASE] at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197) ~[spring-beans-4.3.11.RELEASE.jar:4.3.11.RELEASE] at org.springframework.aop.target.SimpleBeanTargetSource.getTarget(SimpleBeanTargetSource.java:35) ~[spring-aop-4.3.11.RELEASE.jar:4.3.11.RELEASE] at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:192) ~[spring-aop-4.3.11.RELEASE.jar:4.3.11.RELEASE] at com.sun.proxy.$Proxy94.isEmpty(Unknown Source) ~[na:na] at com.fasterxml.jackson.databind.ser.std.MapSerializer.serializeWithType(MapSerializer.java:550) ~[jackson-databind-2.8.10.jar:2.8.10] at com.fasterxml.jackson.databind.ser.std.MapSerializer.serializeWithType(MapSerializer.java:30) ~[jackson-databind-2.8.10.jar:2.8.10] at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:706) ~[jackson-databind-2.8.10.jar:2.8.10] at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:689) ~[jackson-databind-2.8.10.jar:2.8.10] ... 43 common frames omitted Caused by: java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet/DispatcherPortlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request. at org.springframework.web.context.request.RequestContextHolder.currentRequestAttributes(RequestContextHolder.java:131) ~[spring-web-4.3.11.RELEASE.jar:4.3.11.RELEASE] at org.springframework.web.context.request.AbstractRequestAttributesScope.get(AbstractRequestAttributesScope.java:41) ~[spring-web-4.3.11.RELEASE.jar:4.3.11.RELEASE] at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:340) ~[spring-beans-4.3.11.RELEASE.jar:4.3.11.RELEASE] ... 51 common frames omitted
検索してもドンピシャな記事がなく色々と試行錯誤した結果以下のページに行き着きました。
以下のページを参考にRedisTemplate
を作成しました。合わせてHttpSessionConfig
クラスを削除すればredisに登録することができます。
Spring Boot Redis custom json serializer example. · GitHub
実装した結果はこちらです。