Fortranで出力したバイナリをPython側で読み込むプログラムを書いていて、挙動が異なる事象に遭遇したのでメモしておきます。Fortran側のコードはこちら。
program main implicit none integer(4), parameter :: rp = kind(1.0d0) integer(4), parameter :: data1 = 10 real(rp), parameter :: data2 = 2.0_rp complex(rp), parameter :: data3 = cmplx(3.0_rp,4.0_rp,kind=rp) write(6,*) "data1 = ", data1 write(6,*) "data2 = ", data2 write(6,*) "data3 = ", data3 open(10,file="data.dat",form="unformatted",access="stream", & & convert="big_endian",status="replace") write(10) data1, data2, data3 close(10) end program main
コンパイルして実行すると、それぞれの値が標準出力されるとともに data.dat が吐かれます。
$ gfortran main.f90 $ ./a.out data1 = 10 data2 = 2.0000000000000000 data3 = (3.0000000000000000,4.0000000000000000)
Python側でバイナリファイル data.dat に書かれた値を読み込みます。 np.fromfile を使いますが、ここで以下のように、ファイルの指定の仕方を「ファイルオブジェクト」の場合と「ファイル名」にした場合で比較してみます。 np.fromfile のドキュメントを見る限り、どちらでも動作することが期待されますが、実際には「テキスト名」を指定したほうは、実数、複素数は正しく読み取れていません。
# -*- coding: utf-8 -*- import numpy as np f1 = open("data.dat","rb") aa = np.fromfile(f1,">i4",1)[0] bb = np.fromfile(f1,">f8",1)[0] cc = np.fromfile(f1,">c16",1)[0] f1.close() print(aa,bb,cc) f2 = "data.dat" aa = np.fromfile(f2,">i4",1)[0] bb = np.fromfile(f2,">f8",1)[0] cc = np.fromfile(f2,">c16",1)[0] print(aa,bb,cc)
実行結果がこちらです。
$ python3 main.py 10 2.0 (3+4j) 10 2.17504568574e-313 (2.17504568574e-313+5.307579804e-315j)
「ファイルオブジェクト」を指定すれば正常に動作することが分かったので対処法としてはそのようにすればよいのですが、どうにも原因がはっきりしないのがすっきりしません。原因が分かれば記事にしたいと思っています。なお、バージョン情報はこちらです。参考になれば幸いです。
$ python3 -V Python 3.11.2 $ dpkg -s python3-numpy | grep Version Version: 1:1.24.2-1+deb12u1