73186


Pythonで自作モジュールを作成した際に別のPythonファイルで[from
import]という形で読み込む方法はわかるのですが、一発でimportという形にする方法がわかりません。

３個のファイルは同じ階層にあり、test.pyを実行するという形です。  
test.pyを実行した際には以下のようなエラーがでます。

[code]

    Traceback (most recent call last):
      File "test.py", line 3, in <module>
        api = sakanaAPI()
    TypeError: 'module' object is not callable
    
[/code]

__init__py

[code]

    from sakanaAPI import sakanaAPI
    
[/code]

sakana.py

[code]

    class sakanaAPI():
        def get_maguro(self):
          return "maguro"
    
    
[/code]

test.py

[code]

    import sakanaAPI
    
    api = sakanaAPI()
    
    text = api.get_maguro()
    print(text)
    
[/code]


CC BY-SA 4.0
2021-01-09T19:03:05.350
73179
2021-01-10T17:22:04.690
2021-01-09T19:21:02.070
40856
40856
question
python
Pythonの自作モジュールをfrom importではなくimportだけで出来るようにしたい


次のコードはモジュールsakanaからクラスsakanaAPIをインポートしています。
※簡単にいうとモジュールはコードが書かれたファイルです、モジュール名はファイル名から.pyを除いたものです。

[code]

    from sakana import sakanaAPI
    api = sakanaAPI()
    
[/code]

次のコードはモジュールsakanaをインポートしていますが、クラスなどのオブジェクトはインポートしていません。

[code]

    import sakana
    api = sakanaAPI()
    
[/code]

このため、`api = sakanaAPI()`はエラーになります。

[code]

        api = sakanaAPI()
    NameError: name 'sakanaAPI' is not defined
    
[/code]

次のように、クラス名を明示すればエラーは解消します。

[code]

    import sakana
    api = sakana.sakanaAPI()
    
[/code]

### 回答

インポート文には`import`から始まるものと`from`から始まるものがあり、`import
XX`で始まる形式ではクラスをインポートできません。`from XX import yy`の形式でクラスをインポートしてください。

[Documentation » Python 言語リファレンス 7.11. import
文](https://docs.python.org/ja/3/reference/simple_stmts.html?highlight=import#the-
import-statement)には次のように書かれています。

> (from 節が無い) 基本の import 文は 2 つのステップで実行されます:  
>  モジュールを見付け出し、必要であればロードし初期化する  
>  import 文が表れるスコープのローカル名前空間で名前を定義する。

> from 形式ではもう少し複雑な手順を踏みます:  
>  from 節で指定されたモジュールを見付け出し、必要であればロードし初期化する;  
>  import 節で指定されたそれぞれの識別子に対し以下の処理を行う:

* * *

### 余談

`__init__.py`はパッケージを作成するときに使用するものなので、モジュールをパッケージとして管理しないときは必要ありません。  
※また、Python3.3以降では`__init__.py`は必須でなくなったようです。


CC BY-SA 4.0
2021-01-10T00:26:06.950
73180
2021-01-10T01:22:19.137
2021-01-10T01:22:19.137
35558
35558
73179
answer


返信とPython **init**.pyの書き方を参考に記述と、ファイル構成を変えてみました。フォルダーにモジュールをまとめました。  
これによりimport sakanaAPIするだけで読み込めるようになりました。

sakanaAPI  
\-- **init**.py  
\-- sakana.py  
test.py

**init**.py

[code]

    from sakanaAPI.sakana import *
    
[/code]

sakana.py

[code]

    def get_maguro():
     return "maguro"
    
[/code]

test.py

[code]

    import sakanaAPI
    text = sakanaAPI.get_maguro()
    print(text)
    
[/code]

ただ問題としてPythonのclassを使っていないのでコードとして微妙感がありますが、これで問題ないんでしょうか？


CC BY-SA 4.0
2021-01-10T03:42:11.487
73182
2021-01-10T03:42:11.487
40856
73179
answer


[builtins — Built-in
objects](https://docs.python.org/3.8/library/builtins.html)
モジュールを使って、`sakana.sakanaAPI` を `sakanaAPI` という名前でアクセスできる様にする方法も考えられます。  
なお、`__SAKANA_SETUP__` を使っているのは多重インポート時に初期化が何度も行われる事を防ぐためです。

**sakana.py**

[code]

    try:
      __SAKANA_SETUP__
    except NameError:
      __SAKANA_SETUP__ = False
    
    if not __SAKANA_SETUP__:
      class sakanaAPI():
        def get_maguro(self):
          return "maguro"
    
      import builtins
      ## same as `from sakana import sakanaAPI'
      builtins.sakanaAPI = sakanaAPI
    
    __SAKANA_SETUP__ = True
    
[/code]

**test.py**

[code]

    pass
    
    if __name__ == '__main__':
      import sakana
      api = sakanaAPI()
      text = api.get_maguro()
      print(text)
    
[/code]

**実行結果**

[code]

    $ python3 -V
    python3.8.6
    
    $ ls -1
    sakana.py
    test.py
    
    $ python3 test.py
    maguro
    
[/code]


CC BY-SA 4.0
2021-01-10T06:12:11.743
73186
2021-01-10T06:23:47.780
2021-01-10T06:23:47.780
73179
answer