howto/python

コメント


ドキュメント

命名の慣例

2022/06/26+α

pythonでの命名の慣例

* 先頭に _ をつけたものは外部から書き換え禁止。

* 先頭に __ をつけたものはアクセス禁止。

* 関数名は すべて小文字でスネークケース(単語をつなげる場合は _ でつなぐ)。

* 変数は すべて小文字でスネークケース。

* クラス名は アッパーキャメルケース(大文字から始め、単語をつなげる場合は最初を大文字にしてつなぐ)。
  クラスのメソッドの第1引数は selfにする

* 定数は すべて大文字でスネークケース。

* 破棄変数として _ 名のみの変数がある。eg) for _ in range(10): print( "hello" )

* 名前の末尾 _ は名前衝突を避けるために使用される(末尾 __ や  ___ なども)。

* 名前の先頭と末尾 __...__ はpythonが特別な用途として使っているもの。eg) __init__

* パッケージ名は すべて小文字の短い名前で _ は使わない。
  なお、パッケージ名はディレクトリ名やファイル名に対応している。
  eg) import tkinter の tkinter
  eg) import turtle の turtle

* モジュール名は すべて小文字の短い名前で _ を使ってもよい。
  なお、モジュール名は拡張子を除いたファイル名に対応している。
  eg) import tkinter.font の font

[ref]
https://qiita.com/shiracamus/items/bc3bdfc206b39e0a75b2
https://mako-note.com/ja/python-underscore/
https://python.softmoco.com/basics/python-naming-conventions.php

tkinerモジュール

(注) python2は Tkinter、python3は tkinterを importするようだ。名前が異なる。

お気楽 Python/Tkinter 入門 http://www.geocities.jp/m_hiroi/light/pytk01.html

1. Hello world! http://www.shido.info/py/tkinter1.html

PythonのTkinterを使ってみる https://qiita.com/nnahito/items/ad1428a30738b3d93762

実行時間を測る、sleepする

>>> import time
>>> time1 = time.clock()
>>> time2 = time.clock()
>>> print( time2 - time1 )
0.0009600000000000164
>>>
>>> help( time ) #ドキュメントをみる
>>> time1 = time.clock(); time.sleep(10); time2 = time.clock(); print( time2 - time1 )
4.599999999999049e-05

time.clock()は3.8?から廃止されているので time.time()を使う。
sleepを使う。import time しておいて、time.sleep(2)など

いくつかの例

インタプリタ起動

$ python  #たいていpython2が起動するらしい
$ DISPLAY=hostname:0 python3 -B  #python3を起動、バイトコンパイルさせない(-Bオプション)、DISPLAYを指定。

$ export PYTHONDONTWRITEBYTECODE=t  #これでもバイトコンパイルさせないらしい

スクリプトの実行

$ DISPLAY=hoge:0 python3 -B filename.py  #filename.pyを実行する。
$ DISPLAY=hoge:0 ./filename.py           #filename.pyを実行する。

いくつかの例

>>> from turtle import *
>>> for i in range(6):    #図形が表示される
...     forward(100)
...     right(60)
... 
>>> a = "Python3 is awsome!"
>>> a . lower()
'python3 is awsome!'
>>> len(a)
18
>>> (1+2J)/5J
(0.4-0.2j)
>>> for item in [ 'a', 'b', 'c' ]:
...     print( item )
... 
a
b
c
>>> for c, item in enumerate( [ 'a', 'b', 'c' ] ):
...     print( c, item )
... 
0 a
1 b
2 c
>>> f=open("temp.txt", "w")
>>> for c in range(1,101):    #1から100までの数字をファイルに書き出す。
...     f.write( str(c) )
... 
>>> f.close()
>>> [ord(s) for s in "Python"]    #内包記法で文字コードのリストを作る
[80, 121, 116, 104, 111, 110]
>>> val=10; [ x for x in range(1,val+1) if val %x == 0 ]    #内包記法で10の約数のリストを作る
[1, 2, 5, 10]
#二次元配列を作る
>>> a = [ [ str(i)+str(j) for j in range(8)]  for i in range(5) ]
>>> a
[['00', '01', '02', '03', '04', '05', '06', '07'], ['10', '11', '12', '13', '14', '15', '16', '17'], 
['20', '21', '22', '23', '24', '25', '26', '27'], ['30', '31', '32', '33', '34', '35', '36', '37'], 
['40', '41', '42', '43', '44', '45', '46', '47']]
>>> a[4][5]
'45'
>>> int(a[4][5])
45
>>> for i in range(5):
...   a[i]
...
['00', '01', '02', '03', '04', '05', '06', '07']
['10', '11', '12', '13', '14', '15', '16', '17']
['20', '21', '22', '23', '24', '25', '26', '27']
['30', '31', '32', '33', '34', '35', '36', '37']
['40', '41', '42', '43', '44', '45', '46', '47']
>>> i = { "GMT" : "+000", "BST" : "+100", "EET" : "+200", "JST" : "+900" }
>>> i
{'BST': '+100', 'EET': '+200', 'JST': '+900', 'GMT': '+000'}
>>> i.items()
dict_items([('BST', '+100'), ('EET', '+200'), ('JST', '+900'), ('GMT', '+000')])
### dict_items(  ) が付く意味はなに? 辞書型インスタンスの特殊メソッド__repr__の単なる仕様?
>>> import os
>>> os.walk("./")
>>> i=os.walk("./")
>>> next(i)
('./', ['QCLObot', 'ProteinDF_bridge', 'ProteinDF', 'ProteinDF_pytools', 'OpenFOAM', 'LOG_kiku'], 
['2dn2.pdb', '1omb-mod.pdb', 'LOG_kiku.tar', 'p3.py~', 'p3.py', 'temp.txt', 'fws.gro.pdb'])
>>> next(i)
('./QCLObot', ['.git', 'qclobot', 'scripts'], ['.gitignore', 'LICENSE', 'setup.py', 'README.md'])
### 現在作業中のディレクトリ、作業中ディレクトリ内のディレクトリのリスト、作業中ディレクトリ内の
### ファイルのタプルがイテレータ(next(i))で次々と得られる。
>>> from decimal import Decimal
>>> Decimal( '0.1' ) * 3
Decimal('0.3')
### この*はDecimalクラスの特殊メソッド __mul__が使われている。Decimalのインスタンスが生成され(値0.1)、
### __mul__が引数3で動いている。演算結果は __repr__で表示か。
>>> import sys
>>> sys.getfilesystemencoding()
'utf-8'
>>> sys.float_info
sys.float_info(max=1.7976931348623157e+308, max_exp=1024, max_10_exp=308,
min=2.2250738585072014e-308, min_exp=-1021, min_10_exp=-307, dig=15,
mant_dig=53, epsilon=2.220446049250313e-16, radix=2, rounds=1)

スクリプトの例

--------------------------------------------------
#!/usr/bin/env python3                                                                                                     
#-*- coding:utf-8; -*-                                                                                            
import sys

def spamfactory( times ):
    """ スパム工場                                                                                                         
    """
    return "Spam ! " * times

print( spamfactory( 3 ) )
input()
--------------------------------------------------
$ ./p3.py

--------------------------------------------------
#!/usr/bin/env python3                                                                                            
#-*- coding:utf-8; -*-                                                                                            
import os

#p= "./LOG_kiku"                                                                                                  
p= "./"

for path, dirs, files in os.walk( p ):
    for f in files:
        print( path, ":", f )
--------------------------------------------------
$ ./p4.py

みんなのPython 第3版, 柴田亨, SBクリエイティブ (2012) 14章の例、 ファイルはここちら todoapp.tar

#正規表現を使ったファイル一覧の取得
>>> import glob
>>> print glob.glob('/dev/sd?')
['/dev/sda', '/dev/sdb']

その他、個々に置換するとき
>>> import re
>>> [ re.replace('/dev/','') for s in glob.glob('/dev/sd?') ]
['sda', 'sdb']

基本

組み込みデータ型

整数  
浮動小数点  
複素数  
文字列  
リスト  [ 1, 2, 3 ]
タプル  ( 1, 2, 3 )   要素ひとつの場合は ( 1, )とする。( 1 ) = 1 = 整数の値などとなるため
ディクショナリ { k1:v1, k2:v2, k3:v3 }
bytes型  
bool型  
set型  { 1, 2, 3 }
iter  イテレート可能なインスタンスに変換する

備考:
順番があるものが、シーケンス型。
書き換えが可能なものが、書き換え可能型。
書き換え可能でない型は、文字列、タプル(ただし要素追加は可能)と、数値もである(丸ごとの書き換えは可)。
関数の引数は、関数で値を書き換えても、呼び出し元では変わらない(値渡しに相当)。書き換え
可能なものもある(例:リストを渡して、リストの要素を書き換えると呼び出し元でも変更されている)。

型変換

int()  文字列を数値に変換
float() 
str()  
chr()  数値を文字(列)に変換
hext  数値を16進数に変換
bin  数値を2進数に変換
oct  数値を8進数に変換

スライス

リストのインスタンスaについて、a[2:3]などとして要素を取り出すこと。

lambda式

 see Python文法詳細、p197、オライリー

整数除算(商)

i // 2
(iは整数だけでなく、浮動点小数でも切り捨て)

文字列操作

raw文字列  r"C:\path\to\file"
split
join

アンパック代入

 a, b = c, d  #スワップ
 return  a, b
 a, b = foo(hoge)
 x = ( 1, 2, 3, 4, 5 )
 a, *b, c = x  #最初と最後を a, cに、それ以外を bに代入
 print( f"{a}, {b}, {c}" )

リストのアンパック

L=[1, 2, 3]
*L  # 1, 2, 3 の並び(リストではない)
(使用例)
  def foo( a, b, c ):
      hogehoge
  foo( *L )

可変長引数

 *args    タプル
 **kwargs ディクショナリ

def a( *args, **kwargs ):
    print( "*args=", *args )
    #print( "**kwargs=", **kwargs )  # **kwargsは何?
    #print( type(**kwargs) )
    print( "args=", args )
    print( "*kwargs=", *kwargs )
    print( "kwargs=", kwargs )
    ### kwargs.pop( "hoge", default ) で値を得ることもできるらしい。
a( 'zero', 1, 2, 3, term='TERM', val='VAL' )
(出力結果)
*args= zero 1 2 3
args= ('zero', 1, 2, 3)
*kwargs= term val
kwargs= {'term': 'TERM', 'val': 'VAL'}

https://note.nkmk.me/python-args-kwargs-usage/

ゲッターとセッター(プロパティ)

x = property( getx, setx )  # xはアトリビュート、getx, setxはゲッターとセッターのメソッド。
                            # こうしておくと、インスタンス.xで代入や参照ができる。

例(以下をprop.pyとして保存して、コメントにあるようにpython3インタプリタで使う)

class Prop:
    _val = None

    def __init__( self, arg=10.0 ):
        self._val = arg

    def getvv( self ):
        print( "In get, return _val/3.0" )
        return self._val / 3.0

    def setvv( self, arg ):
        print( "In set, set arg*3.0 to _val" )
        self._val = arg * 3.0

    # Prop().val で Prop().getvv() が動いたり(getter)、
    # Prop().val=arg で Prop().setvv(arg) が動いたり(setter)する。
    val = property( getvv, setvv )
#    val = property( getvv )
#    val = property( None, setvv )

    def show( self ):
        print( "In show, _val of Prop object is ", self._val )

class PropAt:
    _val = None

    def __init__( self, arg=10.0 ):
        self._val = arg

    @property  # Prop().vv で次の Prop().vv()が動く
    def vv( self ):
        print( "In get, return _val/3.0" )
        return self._val / 3.0

    @vv.setter  # Prop().vv=arg で次の Prop().vv(arg)が動く
                # setterはpropertyのあとに定義しなくてはならないようだ。
                # また、propertyとsetterとで同じメソッド名の必要あるようだ。
    def vv( self, arg ):
        print( "In set, set arg*3.0 to _val" )
        self._val = arg * 3.0

    def show( self ):
        print( "In show, _val of Prop object is ", self._val )

"""
import prop
import importlib

importlib.reload( prop )  #デバッグ用:prop.pyを修正して再度インポート

# propertyを使った場合
a=prop.Prop() ; a.show() ; a.val = 100 ; a.val ; a.show()
  # In show, _val of Prop object is  10.0
  # In set, set arg*3.0 to _val
  # In get, return _val/3.0
  # 100.0
  # In show, _val of Prop object is  300.0
#100を入れて100を取り出しているように見えるが、
#実際は100*3の値を保持しているインスタンスである。

# @propertyを使った場合
a=prop.PropAt() ; a.show() ; a.vv = 100 ; a.vv ; a.show()
  # In show, _val of Prop object is  10.0
  # In set, set arg*3.0 to _val
  # In get, return _val/3.0
  # 100.0
  # In show, _val of Prop object is  300.0
"""

[ref]
https://www.nblog09.com/w/2019/01/09/python-setter-getter/
https://chaika.hatenablog.com/entry/2020/12/10/083000

標準エラー出力に書き出す

print( "hoge", file=sys.stderr )

コメント

#comment1
'''
comment2a
'''
"""
comment2b
"""

python環境がらみの情報取得

import

モジュールの検索順
1)カレントディレクトリ
2)環境変数PYTHONPATH
3)標準ライブラリ
4)site-packages
import モジュール名
from モジュール名 import クラス名
他に、
from パッケージ名 import サブパッケージ名
from モジュール名 import 関数名
などいろいろある。
importは、グローバルでも、ローカルにでも可能である。
モジュールの再読み込み
import hoge が既に実行されていた場合、再度 import hoge をしても何も
実行はされない。再度、実行する場合は reloadが必要。
なお、マニュアルをみると、完全に挙動が同じなるというわけでななさそうである。
>>> import imp
>>> imp.reload( module )  #なお、import moduleが以前になされていること。

Python3.3まではimp.reload()
Python3.4以降はimportlib.reload()
#importlibの例
import importlib
importlib.reload( dispmodule )  #既にいちどimport dispmoduleしていること

https://docs.python.org/3/library/imp.html#imp.reload

import math
math.sin( 1.23 )
or
from math import sin
sin( 1.23 )
複素数の数学関数を利用するには import cmath をする
πは、import math ののち、math.pi
classはモジュールの中などに定義される。モジュールを importして継承クラスを作れる。

#ファイルbook.py内のBookクラスを利用する例
from book import Book
class Blog ( Book )
or
import book
class Blog ( book.Book )

クラスの初期化メソッド __init__
 ふつうは継承したクラスの初期化メソッドを super().__init__(hoge)として呼ぶ
丸括弧で括るとインポートする複数のモジュールを複数行で書ける
from math import ( sin,
                   cos, tan )
#なお、mathモジュール内の他の関数なども評価されるが、名前空間には登録されていないだけ、と思われる?
同じパッケージを、異なる別名をつけてインポートできる
import hoge as alias1
import hoge as alias2
ここで __init__.pyは一回だけしか評価されない

パッケージ

ディレクトリ階層で束ねられたモジュールの集まり

関数の動的呼び出し

モジュール mod11 の名前空間から、関数を実行するcallableの例

for i in dir( mod11 ):
    print( "================================================", "mod11."+i )
    if i[0:1] == "_":
        print( "SKIP" )
    else:
        if callable( eval("mod11."+i) ):
            print( "RUN" )
            print( eval(  "mod11."+i ) )
            eval(  "mod11."+i+"()" )
        else:
            print( "NOT-RUN" )
            print( eval(  "mod11."+i ) )

クラスメソッドを動的に呼び出したり、引数を渡したりする例

class Hoge:
    def hoge( self, a ):
        ...
    def meth( self ):
        ...
        eval( "self.hoge" )( a )
        ...
のように、meth()の中で呼び出すメソッドを文字列演算等で決めることができ、
引数も渡すことができる。
なお、セキュリティ的に evalに渡す引数は、SQLインジェクションのようなものに
注意する。

複素数の扱い

https://note.nkmk.me/python-complex/

例外処理

globalとnonlocal

globalsとlocals

それぞれグローバル変数、ローカル変数を表示する。追加も可。

>>> b=10
>>> def hoge():
...   c=20
...   print(globals())
...   print(locals())
...
>>> globals()
{ ..., 'b': 10, 'hoge': <function hoge at 0x2adffbbe5040>}
>>> locals()
{ ..., 'b': 10, 'hoge': <function hoge at 0x2adffbbe5040>}
>>> hoge()
{ ..., 'b': 10, 'hoge': <function hoge at 0x2adffbbe5040>}
{'c': 20}
>>> globals()['d']=30
>>> d
30

exec

ソースコードを実行する。他のファイルを読み込んで実行するときは exec( open("hoge.py").read() )

関数内でexecにより定義された変数が、関数終了後に追加されているか消えるかを以下のように調べた。 なお、以下のコードをモジュールとして作り、importさせた場合も結果は同じだった。

>>> import pprint
>>> def delf():
...   global f
...   try: del f
...   except: pass  #1行で書けない?
#G,Lに追加あり
>>> (lambda: exec('f=90', globals(),None     ))(); pprint.pprint({'G':globals(),'L':locals()});delf()  #※
>>> (lambda: exec('f=90', locals(), globals()))(); pprint.pprint({'G':globals(),'L':locals()});delf()
#G,Lに追加無し
>>> (lambda: exec('f=90', None,     None     ))(); pprint.pprint({'G':globals(),'L':locals()});delf()  #デフォルトの動作
>>> (lambda: exec('f=90', globals(),locals() ))(); pprint.pprint({'G':globals(),'L':locals()});delf()
>>> (lambda: exec('f=90', None,     locals() ))(); pprint.pprint({'G':globals(),'L':locals()});delf()
>>> (lambda: exec('f=90', locals(), locals() ))(); pprint.pprint({'G':globals(),'L':locals()});delf()

execによりimportしても同じである。

>>> (lambda: exec('import time,pprint; pprint.pprint({"G":globals(),"L":locals()}); time.sleep(3)'))(); \
    pprint.pprint({'G':globals(),'L':locals()})  #timeは追加無し
>>> (lambda: exec('import time,pprint; pprint.pprint({"G":globals(),"L":locals()}); time.sleep(3)',globals()))(); \
    pprint.pprint({'G':globals(),'L':locals()})  #timeは追加あり

globals, localsの挙動がいまいちよくわからないが、変数を追加する場合は ※にすればよい。 そうでなければデフォルトの動作でよい。 ParaViewのマクロは、importは追加されるが変数は追加無しであるため、execで実行されている訳ではなさそうである。

yeild

https://qiita.com/weedslayer/items/11de0f314ccbb70de812
returnは関数がそのまま終了する。これに対して、yeildは返値を渡し、制御を戻すが、再度関数が呼ばれると 続きから実行される。 返す値が無くなると、StopIteration例外が発生するようだ。

printとformat

print( hogehoge, end='' )  #printで改行しない
  end='\t' だと最後にtabが出力
  sep=',' で複数出力する時のセパレータを指定
  file=ファイルオブジェクト でファイルに出力
          fo=open('file.txt', 'w')とし、file=fo とし、使った後で fo.close()
  flush=True で、出力後にフラッシュ

https://note.nkmk.me/python-format-zero-hex/
https://note.nkmk.me/python-numpy-set-printoptions-float-formatter/

'フォーマット指定の文字列'.format( arg1, arg2, ... )  #フォーマットされた文字列を作る
'{: >+6,}'.format(+123)  #例 
formatを使わなくても、
f'...{argN: >+6,}...' のようにして、同様の文字列を作ることができる
以上は、print関数と一緒に使う必要は無い。
{} のところが argNになる
{ や } をそのまま出力する場合には {{ や }} とする
:  の次が空白だと、余った部分が空白で埋められる。
+  で正の数でも符号を表示、
>6 は6文字以下(6文字以上あるとはみ出して表示)
,  で3桁ずつ,を付ける

{:10x}      で10桁の16進数表示
{: >+12.2f} で12文字以下で、小数点以下が2桁で表示
{: >+12.2e} で同様に指数表現(小数点以下2桁で指数表現)
{: >+12.2g} で有効数字2桁で表示
例)
  print('{: >+6,}'.format(+1234567))
  print('{:10x}'.format(+1234567))
  print('{: >+12.2f}'.format(+1234567))
  print('{: >+12.2e}'.format(+1234567))
  print('{: >+12.2g}'.format(+1234567))
  +1,234,567
      12d687
   +1234567.00
     +1.23e+06
      +1.2e+06
numpyのndarray型のデータをフォーマット指定する場合
  numpy.set_printoptions( formatter={ 'complex_kind' : '{: >+20.4f}'.format } )
  でcomplex128型のデータのndarrayのオブジェクトを出力をすると、
  [     +0.2967-0.4617j      +0.2967-0.4617j]
  などとなる
__str__メソッドを定義すると、print(インスタンス)で__str__を実行して独自の出力を出せる。
例)
  class MC:
    def __init__(self,v):
      self.value = v
    def __str__(self):
      return f"MC instance, value = {self.value}"
  
  print( MC(42) )
  MC instance, value = 42

その他

インデントのタブとスペース

同じスコープのインデントに、タブとスペースが混ざっていたらインデントエラーになる。
どちらかに統一する。

全角スペースは \u3000 である

a="abc\u3000def"
b=open( "hoge.txt", "w" ); print(a,file=b); b.close()

文字の置き換え

"AB789CDあEいFG".translate( "".maketrans("あいABC","ai012") )
これは echo "AB789CDあEいFG" | tr "あいABC" "ai012" のようなものに相当。
ただし trは日本語不可。

文字列内のパタンを検索

パタンに一致した場合、その部分を示すre.Matchのオブジェクトを返す。
reMatchのオブジェクトは、group()によって文字列を受け取れる。
パタンに一致が無かったらNoneを返す。
>>> import re
>>> a=re.search( "\d{4}", "ab12345cd5678ef" )
>>> a
<re.Match object; span=(2, 6), match='1234'>
>>> a.group()  #a=Noneのときは None.group()はエラーになる
'1234'
#1行で、エラー込みで、一致した文字列を受け取る(もっとよい方法は?)
x=re.search( "\d{8}", "ab12345cd5678ef" ); x = x.group() if x else None

https://note.nkmk.me/python-re-match-object-span-group/

リストと辞書とsorted

>>> d=[ ('A','5'), ('B','4'), ('D','1'), ('C','2'), ('E','3'), ('B','9') ]
>>> dict(d)
{'A': '5', 'B': '9', 'D': '1', 'C': '2', 'E': '3'}
#キーが同じものはひとつのみになる。おそらく最後の要素の値になる
>>> dict(d).items()
dict_items([('A', '5'), ('B', '9'), ('D', '1'), ('C', '2'), ('E', '3')])
#辞書をタプルのリストにしたようなものを与える。see help(dict)
>>> sorted(dict(d))  #キーのみ並び替えたリストを与える
['A', 'B', 'C', 'D', 'E']
>>> sorted(dict(d).items())  #(キー,値)の並び替えたリストを与える
[('A', '5'), ('B', '9'), ('C', '2'), ('D', '1'), ('E', '3')]

リストとsort

(注意)
リストのメッソドsortは データを書き換える。
組み込み関数のsortedは 新しいリストを生成して与え、元のリストは書き換えない。
sortは安定な並び替えである。sortedは安定化は不明(helpに無し)。

sortとsortedの違い https://note.nkmk.me/python-list-sort-sorted/

>>> d=[ ('A','5'), ('B','4'), ('D','1'), ('C','2'), ('E','3'), ('B','9') ]
>>> d.sort(key=lambda x: x[1], reverse=True)
>>> d
[('B', '9'), ('A', '5'), ('B', '4'), ('E', '3'), ('C', '2'), ('D', '1')]
>>> d=[ ('A','5'), ('B','4'), ('D','1'), ('C','2'), ('E','3'), ('B','9') ]
>>> d.sort(key=lambda x: x[0], reverse=True)
>>> d
[('E', '3'), ('D', '1'), ('C', '2'), ('B', '4'), ('B', '9'), ('A', '5')]
途中にprint文を挟めた例(なお、stderrに出力させないとキーの値に使われる)
>>> d=[ ('A','5'), ('B','4'), ('D','1'), ('C','2'), ('E','3'), ('B','9') ]
>>> d.sort(key=lambda x: (print(x, x[1], file=sys.stderr), x[1]), reverse=True)
('A', '5') 5
('B', '4') 4
('D', '1') 1
('C', '2') 2
('E', '3') 3
('B', '9') 9
>>> d
[('B', '9'), ('A', '5'), ('B', '4'), ('E', '3'), ('C', '2'), ('D', '1')]

リスト、辞書の整形出力

import pprint
pprint.pprint( list_val, widhth=160 )

https://note.nkmk.me/python-pprint-pretty-print/

ファイルをseek

先頭にする例
fp.seek(0,0)  # offset=0, referencepoint=0 でファイル位置変更

比較演算の組み合わせ

w = 3
2 <= w and w <= 8
2 <= w <= 8   #上記と同じ

zip

x = ( 1, 2, 3, 4, 5 )
y = ( 10, 20, 30, 40, 50 )
for i, j in zip( x, y ):
  print( i, j )

辞書のループ

z = {'a': 1, 'b': 2, 'c':3 }
for key, val in z.items():
  print( key, val )
for k in z.keys():
  print( k )
for v in z.values():
  print( v )

Excelのワークブックの読み書き

import openpyxl
wb=openpyxl.load_workbook("testbook.xlsx", data_only=True)
wksheet=wb["Sheet1"]
for i in wksheet.iter_rows(min_row=2):
    print( "i=", i, "i[0].row=", i[0].row )
# 各行のループ変数 iは、excelのセルを要素とするタプルが入っている。
# i[0], i[1], ..., i[p], ... は左からp番目のセルである。
# i[p].rowはそのセルがexcelのシートで何行目かの番号である。
wb = openpyxl.load_workbook( 'sample.xlsx')  #ワークブックの読み込み
wb = openpyxl.Workbook()  #新規ワークブック生成、
wb.sheetnames     #シート名のリスト(新規の場合、シートは"Sheet"のみ)
wb.active         #現在選択されているシート(新規の場合、"Sheet")
st = wb.active    #現在選択されているシート
st.title = 'Sheet100'  #シート名変更
st2 = wb[ st.title ]  #シートの取得
True if id(st) == id(st2) else False  #Trueが返るのでstとst2は同じもの
st2[ "D2" ] = "d-2 cell contents"  #セルに代入
st2.merge_cells( "D3:f4" )         #セルを結合
st2[ "D3" ] = "combined d-3 cell contents"
st2[ "D3" ].alignment = openpyxl.styles.alignment\
                        .Alignment( vertical="center" )  #中央配置
wb.save( "wb-temp.xlsx" )  #ワークブックの保存

https://gammasoft.jp/support/how-to-use-openpyxl-for-excel-file/
https://atmarkit.itmedia.co.jp/ait/articles/2202/08/news031.html
https://note.nkmk.me/python-openpyxl-usage/

csvファイルを読む

#csvのフォーマットは生成するソフトに依存しているため注意。Excelの推奨形式は
#csv.readerで大丈夫らしい。
import csv
fp=open( "testbook.csv", encoding='utf-8-sig' )  #BOM付きのファイルの場合
list( csv.reader( fp ) )

または list(...) の代わりに
ite=csv.reader( fp )  #_csv.reader関数を返す(イテレータ機能をもつ)
                      #_csvはモジュールらしい。_csvは import _csv;  _csv.__file__
                      #してみると、.soの共有ライブラリのファイルである。
                      #help(_csv); type(_csv); type(_csv).mro() をみよ。
for r in ite:    #rはcsvの各行のリスト
    for c in r:   #各行について、cは列の項目
        print( c, end=' / ', file=sys.stdout )
    print( file=sys.stdout )

(注) openするとき、BOMがある場合は必ず encoding='utf-8-sig' を指定する。 さもないと、読み込んだ最初の項目の先頭に BOMを示す文字( "\ufeff" )が付いてしまう。 確か、Excelアプリで xlsxから csvを作ると BOM付きである。 BOMなしのファイルは encoding='utf-8-sig' でオープンしても構わないようだ。

https://qiita.com/msk02/items/c3a1c4a1e1ef94c37228
https://www.lifewithpython.com/2017/10/python-detect-bom-in-utf8-file.html

fp=open( "testbook.csv" )  #環境に依るが たいていデフォルトで encoding='utf-8'
fp=open( "testbook.csv", encoding='utf-8' )      #BOMなしファイル
fp=open( "testbook.csv", encoding='utf-8-sig' )  #BOMつきファイル
#- - - - - - - - - - - - - - - - - - - - -
#ファイルdisp.py
def disp(ite):
    fo=open( "disp-temp.txt", "w" )  #BOMなしで書き出し
    for r in ite:
        for c in r:
            print( c, end=' / ', file=fo )
        print( file=fo)
    fo.close()
#- - - - - - - - - - - - - - - - - - - - -
を作っておいて
>>> import disp
>>> disp.disp( ite )  # iteは上のもの
のように使える。

パッケージとモジュールの構造(まとめ)

説明の前提(用語、予備知識)

次のディレクトリ階層を仮定して、以下を説明。

 mytp
 |-- __init__.py
 |-- mod01.py
 |-- mod02.py
 `-- mysp1
     |-- __init__.py
     |-- mod11.py
     `-- mod12.py
 いま、mod01,02,11,12内に 関数func01,02,11,12があるとする。
 また、インポートのために、mytpを含むディレクトリが PYTHONPATH環境変数などに含まれていること。

パッケージ = ディレクトリ, 例 mytp

サブパッケージ = サブディレクトリ, 例 mysp1

モジュール = ファイル, 例 mod01.pyなど

オブジェクト = モジュール、関数、などなど

オブジェクト名は、名前空間でもあり、名前空間には名前空間(オブジェクト)を階層的に含むようだ。 最初に pythonが実行している名前空間は __main__ である。 (__main__で import hoge すると __main__内に hogeの名前空間が作られると思うが、 __main__.hoge のような記述はできないようで、暗黙的に __main__. が付くと思われる。ちょっとちがう?)

名前空間に登録されている名前は dir() で知ることができる。

__name__                 # 現在の名前空間
dir( [オブジェクト名] )  # オブジェクト名(名前空間)に登録されている名前(インスタンス名、関数名、
                         # 名前空間名など)のリスト。

(トップレベルの) パッケージのインポート

import mytp  # mytp/__init__.pyがあれば実行される。
             # 現在の名前空間に mytpが追加されるが、mytp/__init__.pyが無かったり、空であれば、
             # mytpの名前空間もほぼ空のままであり mytp.mod01などは使用できない。
import mytp.mod01    # 現在の名前空間にmytpが追加され、mytpの名前空間に mod01が追加され、
                     # mod01モジュールの関数などが使用できる。
mytp.mod01.func01()
from mytp import mod01  # mytpディレクトリの mod01が、現在の名前空間に追加される。
                        # mod01モジュールの関数などが使用できる。
mod01.func01()
from mytp.mod01 import func01  # mytpディレクトリのmod01内の func01が、現在の名前空間に追加され、
                               # そのままで func01を使用できる。
                       # 追記:func01がモジュールスコープ(今の場合mod01)にて if文を使って条件に
                       #よって defされている関数であってもよいらしい。
func01()
  print( "* __name__ = ", __name__ )  # このパッケージ名 mytp となっている

  # __main__で import mytp としただけで mytp.mod01.func01() が使用できるようになる。
  from mytp import mod01  # mytpの名前空間に mod01が追加される。mytp は . でもよいようだ
  from mytp import mod02  # mytpの名前空間に mod01が追加される。mytp は . でもよいようだ

  #このファイル ( 名前空間 mytp ) では mod01.func01() が使用できる。
  mod01.func01()

  # 関数は名前空間 mytp に登録されるため、 mytp.initmytp() で使用できる。
  def initmypt():
      print( "initmypt" )

サブパッケージのインポート

import mytp.mysp1        # mytp/__init__.pyがあれば実行される。
                         # 現在の名前空間に mytpが追加される。
                         # mytp/mysp1/__init__.pyがあれば実行される。
                         # mytp名前空間に mysp1が追加されるが、mysp1の名前空間はほぼ空であり、
                         # mytp.mysp1.mod11などは使用できない。(状況は import mytp と同じ)。
from mytp import mysp1   # mytp/__init__.pyがあれば実行される。
                         # mytp/mysp1/__init__.pyがあれば実行される。
                         # 現在の名前空間に mysp1が追加されるが、mysp1の名前空間はほぼ空であり、
                         # mysp1.mod11などは使用できない。(状況は import mytp と同じ)。
import mytp.mysp1.mod11    # mytp/__init__.pyがあれば実行される。
                           # mytp/mysp1/__init__.pyがあれば実行される。
                           # 現在の名前空間にmytpが追加され、mytpの名前空間に mysp1が追加され、
                           # mysp1の名前空間に mod11が追加され、
                           # mod11モジュールの関数などが使用できる。
mytp.mysp1.mod11.func11()
from mytp.mysp1 import mod11  # mytp/__init__.pyがあれば実行される。
                              # mytp/mysp1/__init__.pyがあれば実行される。
                              # mytp/mysp1ディレクトリの mod11が、現在の名前空間に追加される。
                              # mod11モジュールの関数などが使用できる。
mod11.func11()
from mytp.mysp1.mod11 import func11  # mytp/mysp1ディレクトリのmod11内の func11が、現在の名前空間に追加され、
                                     # そのままで func11を使用できる。
func11()
  print( "* __name__ = ", __name__ )  # このパッケージ名+サブパッケージ名 mytp.mysp1 となっている

  # __main__で import mytp としてもこのサブパッケージは読み込まれない。
  # import mytp.mysp1 とすると mytp.mysp1.mod11.func11() などが使用できるようになる。
  from mytp.mysp1 import mod11  # mytp.mysp1の名前空間に mod11が追加される。mytp は . でもよいようだ
  from mytp.mysp1 import mod12  # mytp.mysp1の名前空間に mod12が追加される。mytp は . でもよいようだ

  # __main__で from mytp import mysp1 とすると mysp1 が名前空間に追加され、mysp1.mod11.func11()など
  # が使用できるようになる。

  #このファイル ( 名前空間 mytp.mysp1 ) では mod11.func11() などが使用できる。
  mod11.func11()

  # 関数は名前空間 mytp.mysp1 に登録されるため、 mytp.mysp1.initmysp1() で使用できる。
  def initmysp1():
      print( "initmysp1" )

(__main__などからの) パッケージ、サブパッケージの使い方

1) myptや mytp.mysp1をインポートして、mytpからfunc11を指定する。

import mypt
mypt.mod01.func01()
import mytp.mysp1
mytp.mysp1.mod11.func11()
import mytp.mysp1 as subn
subn.mod11.func11()

2) mod01や mod11, mysp1をインポートして、mod01や mod11, mysp1からfunc11などを指定する。

from mytp import mod01
mod01.func01()
from mytp.mysp1 import mod11
mod11.func11()
from mytp import mysp1
mysp1.mod11.func11()

その他 __main__.pyなど

python -m モジュール名 で、モジュールを読み込み。そのモジュールのディレクトリにある __main__.pyを実行する(無ければエラー)。 __init__.pyがあれば事前に実行される。

python -m bcone で bcone/__main__.pyを実行させるのがめんどいなら、 alias bcone='python -m bcone' するとよいだろう。 また、__main__.pyで他のファイルを実行したい時は、import bcone.main とするとよいでしょう(この場合は bcone/main.pyが実行)。

setup.cfg :
パッケージインストールに関するひとつのファイルである。 中の entry_pointで /usr/bin内に置くコマンドと、そのコマンドにより実行される パッケージ内のpython関数を指定することができるらしい。
setup.py :
似たようなもの。setuptoolsをimportして使われるようだ。

python -c 'import hoge; hoge.func()' などコードを-cオプションで実行する。importの前に空白があると インデントエラーになる。'...'の文字列を改行込みでタイプしても良い。

matplotlibモジュール

numpy, scipyのドキュメント

scipyモジュール

scipy.integrate.RK45クラスの説明

https://docs.scipy.org/doc/scipy/reference/generated/scipy.integrate.RK45.html
import scipy.integrate; help(scipy.integrate.RK45) も同じ情報が表示される
c.f. help(scipy.integrate.solve_ivp)

http://www.physics.okayama-u.ac.jp/~otsuki/lecture/CompPhys2/ode/ode.html
RK45は5次のルンゲクッタ法を使用して、4次のルンゲクッタ法のステップサイズを制御している。 また、マニュアル help(solve_ivp) によると、RK45は複素数も利用できる。 ただし、初期値が実数であっても、複素数のデータ型で与えること。

numpyモジュール

ndarray型と matrix型

以下は 二次元配列の ndarray型
( type(a)でインスタンスの型を調べられる。また、下の float64の 64などは環境依存だろう )

a=numpy.zeros( (2,2) )  # 2行2列のfloat64のゼロで初期化した二次元配列を作る
                        # a.dtypeは float64

a=numpy.array( [[1,2],[3,4]] )  # 組み込みリスト型から、二次元配列を作る
                                # a.dtypeは int64, リストの要素が整数なので
 
a=numpy.empty( (2,2) )  # 2行2列のfloat64の未初期化の二次元配列を作る
                        # a.dtypeは float64

a=numpy.array( [[1,2],[3,4]], dtype='complex128')  # dtype指定もできる
                                                   # ビット数を省略するとpythonの組込み型のビット数(環境依存)となる
b=numpy.zeros_like( a, dtype='float64' )   # aと同じ配列サイズのゼロで初期化した多次元配列を作る
b[:,:] = 1.2                 #すべての要素を 1.2にする
b = b.astype( numpy.int64 )  #要素のdtypeをint64に変換する。要素は型変換される
以下は matrix型(二次元配列に限定され、扱いはndarrayと同じではない)

a=numpy.matrix( [[1,2],[3,4]] )   # 組み込みリスト型から作る
                                  # a.dtypeは int64, リストの要素が整数なので

scipyモジュールは、matrixは使わずに、ndarrayを利用しているようだ。

ndarrayで要素毎に型の違う配列を扱う事も出来るが、その場合には pandasモジュールの方が便利らしい。

行列の用意、初期化など https://note.nkmk.me/python-numpy-zeros-ones-full/
データ型の指定、など https://note.nkmk.me/python-numpy-dtype-astype/

numpy.ndarray型 https://note.nkmk.me/python-list-array-numpy-ndarray/
二次元配列と行列の演算など https://note.nkmk.me/python-numpy-matrix/

Python組み込み型変数のビット数を調べる

numpy.float_  #らしい。この例は floatについて調べている

2次元配列と行列

ndarrayの要素・行などの参照 https://note.nkmk.me/python-numpy-select-element-row-column-array/

a=numpy.array( [[1,2],[3,4]] ) の2次元配列のとき

a[0,1] や a[0][1] は (0,1)要素

スライスで参照できる、代入もできる
a[0,:]   は 0行目の1次元配列(次元がひとつ減る)
a[0:1,:] は 0行目からなる2次元配列
a[:,0]   は 0列目からなる1次元配列(次元がひとつ減る)
a[:,0:1] は 0列目からなる2次元配列
a[:,0] = 9  #参照したすべての要素に 9を代入(右辺が配列の場合、サイズが合うなどすれば代入可)
  次元がひとつ減る => スライスではなく、数字の指定で減る

2次元配列や1次元配列を使って行列演算ができる。 numpy.dot関数、 dotメソッド や @ メソッド、で掛算(matrix型の場合は * メソッドも掛算)。

なお、2次元配列と1次元配列の掛算では、 1次元配列が、演算の左にある場合は行ベクトル、右にある場合は列ベクトルの2次元配列のように扱われる。 そして、1次元配列同士の掛算は内積になる。

dtype型の違う2次元配列(行列)の演算は、高いほうの型に変換されるようである。(どちらが高い型かの順番は?)

ブーリアンインデックスによる参照、代入も可

a[ :, (True,True,False,False) ] 

ファンシーインデックスによる参照、代入も可

a[ :, (0,1) ]   #参照する列の添え字を指定(重複可)、代入も可。
a > 5       # 配列aの各要素が、条件に対して Trueか Falseかになった配列(ブーリアンインデックス)が返る
a[ a > 5 ]  # 5より大きい要素のみを指定して参照、代入も可。参照の結果は1次元配列化されて得られる

複数の次元で指定する場合は a[ numpy.ix_( (False,True,True), (True,False,True,False) ) ] のように ix_関数 を使わないと正しく指定できない。 また、 3次元以上の配列は、ひとつの次元で指定することしか出来ないようである(期待通りの結果にはならないとのこと)。

(※注) 配列がビューではなく、コピーで作られてしまっている場合(生じうる?)は、代入しても値は変化しない

多次元配列の次元を減らす

多次元配列を1次元化する https://note.nkmk.me/python-numpy-ravel-flatten/
多次元配列の次元を減らす https://codechacha.com/ja/python-flatten-list/

a=numpy.arange(12).reshape( (3, 4) )  # 0~11の要素をもつ 3x4行列
a.reshape(-1)  # 数字ひとつなので1次元配列。サイズ -1は自動で決められる(この場合は要素数)
a.ravel()   #可能な限りビューを返す
a.flatten() #データはビューでは無く、必ずコピーされる
などなど

多次元配列の形状を変える https://note.nkmk.me/python-numpy-reshape-usage/

a=numpy.arange(12).reshape( (3,4) )
a.reshape( (4,3) )  # データはコピーされるが、データの1次元的なメモリー配置変わらなく
                    # サイズが切り直されるような形。
                    # 可能な限りビューが返る。
a.reshape( (4,3) ).copy()  # 明示的にコピーを返したい場合
# 引数で、変換順序 order='C' (デフォルト) や 'F' などの指定はできるが、使い道はない?
# a.reshape( (4,3) ) をそのまま端末に出力した場合と、printで出力した場合で、表示のされ方が異なる。
# order='C' や order='F' を指定した場合の挙動がよくわからない。

配列の次元、サイズを調べる

a=numpy.arange(12).reshape( (3, 4) )
a.ndim
a.shape

reshape関数の仕様を調べる

import numpy as np
type( a )  # aが numpy.ndarray のとき
help( np.ndarray ) # import numpy as np してると、typeで numpy. と出るが、numpy. ではなく np. で指定する
                   # reshapeメソッドの説明はあるが、numpy.reshapeを見よとある
help( np.reshape )  # 引数newsharpは、intか intのタプルとある

ビュー(view)とコピー(copy)

https://note.nkmk.me/python-numpy-view-copy-shares-memory/

a.copy()  #コピーを生成する
rcd = a.base is None  #Trueなら、ビューである

mutable(ミュータブル)とimmutable(イミュータブル)

『オブジェクトによっては 値 を変更することが可能です。 値を変更できるオブジェクトのことを mutable と呼ぶ。 生成後に値を変更できないオブジェクトのことを immutable と呼ぶ。 (mutableなオブジェクトへの参照を格納している immutableなコンテナオブジェクトの値は、 その格納しているオブジェクトの値が変化した時に変化するが、コンテナがどのオブジェクトを 格納しているのかが変化しないのであれば immutableです。 immutable かどうかは値が変更可能かどうかと無関係。) オブジェクトが mutable かどうかはその型によって決まる』
[ref] https://docs.python.org/ja/3/reference/datamodel.html から改変

c.f.
オブジェクトは、同一性(identity)、型、値をもつ。
id() 関数は同一性を表す整数を返します。
CPython では、id(x) は x が格納されているメモリ上のアドレスを返す。
組み込みのデータ型のうち、list, set, dict型のみmutable。

def print_id_obj( obj ):
    print( 'id=', id(obj), '  obj=', obj )
a=1
b=a
print_id_obj(a)
print_id_obj(b)
print()
b=2
print_id_obj(a)
print_id_obj(b)

numpy.stack, hstack, vstack

a = numpy.arange(4).reshape( (-1,) ) +100  #[100 101 102 103]
b = numpy.arange(4).reshape( (-1,) ) +200  #[200 201 202 203]

numpy.hstack( [a,b] )  # [100 101 102 103 200 201 202 203] になる

numpy.vstack( [a,b] )  # [[100 101 102 103]
                       #  [200 201 202 203]] になる
numpy.stack( [a,b], axis=0 )  # hstackと同じ

numpy.stack( [a,b], axis=1 )  # [[100 200]
                              #  [101 201]
                              #  [102 202]
                              #  [103 203]] になる

numpy.meshgrid

ax = numpy.linspace(0,4,5).astype(int)    #[   0    1    2    3    4]
ay = numpy.linspace(10,14,5).astype(int)  #[  10   11   12   13   14]

x, y = numpy.meshgrid( ax, ay )
# x
# [[   0    1    2    3    4]
#  [   0    1    2    3    4]
#  [   0    1    2    3    4]
#  [   0    1    2    3    4]
#  [   0    1    2    3    4]]
# y
# [[  10   10   10   10   10]
#  [  11   11   11   11   11]
#  [  12   12   12   12   12]
#  [  13   13   13   13   13]
#  [  14   14   14   14   14]]

for j in range(4,0,-1):
    for i in range(0,4,+1):
        print( " {: >2d}-{: >2d}".format(x[j,i], y[j,i]), end="" )
    print()
#  0-14  1-14  2-14  3-14
#  0-13  1-13  2-13  3-13
#  0-12  1-12  2-12  3-12
#  0-11  1-11  2-11  3-11

xx = x / 2.0
yy = y / 2.0
for j in range(4,0,-1):
    for i in range(0,4,+1):
        print( " {: >3.1f}-{: >3.1f}".format(xx[j,i], yy[j,i]), end="" )
    print()
# 0.0-7.0 0.5-7.0 1.0-7.0 1.5-7.0
# 0.0-6.5 0.5-6.5 1.0-6.5 1.5-6.5
# 0.0-6.0 0.5-6.0 1.0-6.0 1.5-6.0
# 0.0-5.5 0.5-5.5 1.0-5.5 1.5-5.5

numpy.diff

a = np.arange(10).reshape( (-1,) );  b = a*a    # b[i] , i=0~9
c = numpy.diff( b, n=1 )   # c[i] = b[i+1] - b[i] , i=0~8
d = numpy.diff( c, n=1 )   # d[i] = c[i+1] - c[i] , i=0~7
numpy.diff( b, n=2 )       # d[i]と同じ(n回 diffを繰り返す)。二階微分の、中央差分近似に対応

numpy.where

a = numpy.arange(10).reshape( (-1,) )
numpy.where( 5<a, 9.5, 0.5 )    # 配列aの要素が条件( 5< )を満たすとき 9.5、否なら 0.5
numpy.where( 5<a )              # 条件を満たす要素だけの配列(のタプルが返る)
numpy.where( 5<a )[0]           # 条件を満たす要素だけの配列

mpi4pyモジュール

MPIモジュールによる並列化
importすると、並列実行すると思われる。

comm = MPI.COMM_WORLD

anacondaなどによる環境作成

パッケージ(pythonやモジュール)のインストール方法の種類

python自体のインストールと利用バージョン切替

モジュール・パッケージのインストールと使用・不使用切替

anacondaによる condaコマンドは、

  1. 科学計算技術計算のモジュールが豊富(らしい)
  2. condaによる環境切替ができる(pythonバージョンやモジュール)

そのため、モジュール間の依存バージョン、依存するpython自体のバージョン、の整合性をとるには condaが楽だろう。 なお、"環境"は、実際には仮想ではないが "仮想環境"と呼ばれている。

リンク

conda環境の利用方法

conda activate [環境名]  #アクティベート(環境を設定)
conda deactivate         #デアクティベート(環境を終了)
conda create -n 環境名 [python[=バージョン] [パッケージ名[=バージョン]] [...]]  #環境作成
conda remove -n 環境名 --all  #環境の削除
(補足)
conda create -n hoge により、インストール場所の/share/apps/anaconda3/{pkgs,envs} 
や ~/.conda/envs にパッケージや環境が置かれるようだ。

例えば appbinユーザにより /share/apps/anaconda3に anacondaがインストールされているとする。
シェルコマンド
  eval "$(/share/apps/anaconda3/bin/conda shell.bash hook)"
により、appbinや他のユーザは conda環境を利用できる。

- appbinユーザにより作成された環境は /share/apps/anaconda3/{pkgs,envs} にファイルが置かれ、
  他のユーザも利用できる。

- 個人のユーザが環境を作った場合には ~/.conda/envs ともともとの /share/apps/anaconda3/pkgs に
  ファイルが置かれて、そのユーザが利用できる。
- conda create -p pathEnvName により、環境のファイルを置く場所を指定できるため、そのユーザ以外も利用
できるようにできる、らしい。(/share/apps/envsを指定するなど?)
(補足2:パッケージの追加インストール)
 各仮想環境へパッケージを追加インストールするには appbinグループを使用して行う。
 (appbinアカウントによるインストールは、誰が入れたか不明になるため非推奨。)
 追加されたパッケージは、他のユーザも利用できるようになる。
 (注1) 依存関係でパッケージのアップデートも必要に応じて行われるため、その場合は
       既存の環境が変更を受ける。アップデートに伴い不具合が出る可能性がある。
       アップデートされたパッケージをすべてアンインストールしてもとに戻すことは
       ほぼ絶望的である。
        環境を壊す危険が高い場合など、検証用にanacondaを別途でインストールをして確認後に、
       パッケージをアップデートするのが望ましい。
 (注2) pipコマンドは /share/app/anaconda3のすべての既存の仮想環境を壊しうるので、使用しない。
       pipを使用した仮想環境は、condaとpipのパッケージの整合性はチェックされないようなので
       不具合が出うる。
        pipでインストールしたパッケージを pipでアンインストールすると、同じパッケージが 
       condaに存在していても利用できなくなるようだ。少なくともpyqt5はそうなった、他の
       仮想環境への影響は今のところ無さそうである。2023/08/09

 appbinグループを使用した追加方法は、
 sgコマンドまたはnewgrpコマンドにより、所属グループをappbinに変更後にインストール操作
 をする。手順は以下 1)-3) のいずれか
 1) $ sg appbin bash
    $ インストール作業
    $ exit
 2) $ sg appbin "インストールのためのコマンドライン"  #第3引数は引用符で括る
 3) $ newgrp appbin
    $ インストール作業
    $ exit
 なお、所属グループをappbinに変更し忘れた場合は、
 chown -R :appbin /share/apps/anaconda3 をすればよいようだ(not permittedは多量に出る)。
 (rootユーザが chown -R :appbin /share/apps/anaconda3 をしても同様)

 仮想環境の追加作成のときは appbinアカウントを使用する。
 環境は /share/apps/anaconda3/envsに、パッケージは /share/apps/anaconda3/pkgsに入る。

 個人ユーザで conda create -n py36 python=3.6 などで仮想環境を作ることもできる。
 この場合、仮想環境は ~/.conda/envsに、パッケージは /share/apps/anaconda3/pkgsに入る。
 そのためこの場合も作成時には appbinグループを使用すること。

 個人的にいろいろ試す場合は、個人環境に別途でanacondaをインストールすればよい。
conda info       #condaの情報
conda info -e    #環境のリスト
conda -V         #バージョン
conda -h         #ヘルプ
conda config --help     #コマンドconfigのヘルプ
anaconda search --help  #コマンドsearchのヘルプ
conda create --help  #コマンドcreateのヘルプ
conda search [-c チャネル] [--full-name] パッケージ名  #パッケージのバージョンに対応するpythonのバージョン表示
conda install パッケージ名[=バージョン]    #現在の環境に、パッケージをインストール
conda uninstall パッケージ名  #現在の環境から、パッケージをアンインストール
conda list [-n 環境名]                   #インストールされているパッケージのリスト

デフォルト以外のチャンネル: https://docs.conda.io/projects/conda/en/latest/user-guide/concepts/channels.html

環境の保存や、それを使った環境作成
 conda env export > ファイル名.yaml
 conda env create -n 新しい環境名 -f ファイル名.yaml
   or
   デフォルトのチャネルだけなら
   conda list --export > ファイル名.txt
   conda create -n 新しい環境名 -f ファイル名.txt
conda clean --all  #不要なパッケージやキャッシュを削除
conda create -n 新しい環境名 --clone もとの環境名  #環境名を変更する
conda remove -n もとの環境名 --all
conda config --set env_prompt "({default_env}) "  #デフォルトでconda環境のときに付くプロンプトのプレフィックス
conda config --set env_prompt "p:"                #プロンプトプレフィックスを変更

conda config --set changeps1 false  #プロンプトを変更しない
echo $CONDA_SHLVL                   #0以外でconda環境であることを確認できる

conda config --set auto_activate_base false  #conda環境に入ったとき自動的にbase環境をactivateしない、たぶん。
標準的なパッケージをごっそり入れる?
 conda create -n 新しい環境名 [python=バージョン] anaconda
アップデート
 conda update -n base -c defaults conda   #condaのupdate? base仮想環境もupdateされる?
 conda update conda;conda update anaconda;conda update --all  #conda,anacondaのアップデート?,全パッケージがupdate

アンインストール
 次のものを削除するようだ。
 インストール先のanaconda3 ディレクトリ
 ~/.conda ディレクトリ
 ~/.condarc ファイル
 ~/.bashrcに追加された conda initialize のブロック

ハードリンク

スクリプトを実行する時だけ conda activateする(通常は OSデフォルトのpythonバージョンが動くままにしておきたい)

下記のようなスクリプトを mypyなどとして作っておき、mypy hoge.py などとする。

#!/bin/bash --norc

#==== set your python env ====
MYPYTHON=py370

if [ $# == 0 ]; then
   echo "usage: $0 command [args]" >&2
   exit 1
fi

source /share/apps/anaconda3.bash_conda
conda activate $MYPYTHON

#==== execute command [args] ====
"$@"

実行時の symbol lookup error や relocation error の対処

pythonプログラムを実行したときに symbol lookup error や relocation error が出た場合は、 LABO/Rocksのページの対処法を見よ。

弘大JupyterHub

Jupyter Notebook

alliumのjupyter notebook

使用方法は LABO/Rocks#tdb7fe60を見よ。

長い出力部分の表示切替

括弧などの入力補完(autoCloseBrackets)をオフにする

from notebook.services.config import ConfigManager
c = ConfigManager()
c.update('notebook',
         {"CodeCell": {"cm_config": {"autoCloseBrackets": False}}})
を実行して、ノートブックを開きなおす。設定は ~/.jupyter/nbconfig/notebook.json に保存される。

ipynbをpyに変換する

jupyter nbconvert --to python hogehoge.ipynb   #==> hogehoge.pyが作られる

jupytextを使えるようにする(ipynbとpyの同期)

デフォルト以外のチャンネル https://docs.conda.io/projects/conda/en/latest/user-guide/concepts/channels.htmlhttps://conda-forge.org/feedstock-outputs/ より conda-forgeにあるパッケージとして jupytextを検索して https://github.com/conda-forge/jupytext-feedstock を参考に、

$ conda activate py370
$ conda install jupytext --channel conda-forge

のようにパッケージをインストールする(/share/apps/anaconda3でインストール済)。

jupyter notebookを起動して hoge.ipynbファイルを開く→ファイル→Jupytext →Pair Notebook with light Scriptにチェックを入れる。 これで hoge.ipynbと hoge.pyが同期される。 [ref] https://qiita.com/ku_a_i/items/ccdeb7f1d9384fb4767b


トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS