web-dev-qa-db-ja.com

ImportErrorを除く '内のモジュール名をチェックしています'

try:
   import MySQLdb
   # some action
except ImportError as err:
   # fallback code

PyCharmはそれについてコード検査の警告を出します:

'exceptImportError'を含むtryブロックの 'MySQLdb'も、exceptブロックで定義する必要があります

この検査では、解決する必要があるが解決しない名前が検出されます。動的ディスパッチとダックタイピングにより、これは限られた、しかし有用な数のケースで可能です。トップレベルおよびクラスレベルのアイテムは、インスタンスアイテムよりも適切にサポートされます。

わかりました、警告は妥当だと思いました。fallback codeは、「MySQLdb」がインストールされていないことを前提としていますが、ImportErrorを発生させた別のエラーである可能性があります。だから私は次のようなものを使用しました:

try:
   import MySQLdb
   # some action
except ImportError as err:
   if "MySQLdb" in repr(err):
       # fallback code
   else:
       raise

PyCharmアラートはまだ存在しますが、それは単なるPyCharmの問題である可能性があります(Googleはそのような検査に関する問題を示しています)

質問:

  1. 「ImportErrorを除く」ときに名前を確認する価値は本当にありますか?単純な場合でも(some actionimport MySQLdb)?

  2. チェックする価値がある場合、上記の例はそれを行う正しい方法ですか?いいえの場合-正しい方法は何ですか?

P.S。 MySQLdbは、システムに存在しない可能性のあるモジュールの単なる例です。

18
MajesticRa

警告を誤解したと思います。exceptブロックでMySQLdbという変数を定義しないと、後でモジュールを使用しようとするとNameErrorが返されます。

try:
    import foo
except ImportError:
    pass

foo.say_foo() #foo may or may not be defined at this point!

モジュールがtry:句でのみ使用されている場合、これは問題ではありません。しかし、より一般的なケースでは、チェッカーは、exceptブロックで変数を定義することを期待しています。

try:
    import foo
except ImportError:
    foo = None  #now foo always exists

if foo: #if the module is present
    foo.say_foo()
else:
    print("foo") #backup use

モジュールがtryブロックでのみ使用されている場合は、名前空間からモジュールを削除することで、後でモジュールを使用できないことをチェッカー(および自分自身)に示すことができます。

try:
    import foo
    foo.do_thing()
    del foo #optional module should not be relied on outside this try block
except ImportError:
    pass

# now foo never exists here, checker is happy.
20

Python 3.3+では、 ImportError には、インポートが失敗したモジュールの名前を示す属性nameがあります。もちろん、MySQLdbは、Python 2で立ち往生していることを示唆します。

4
Antti Haapala

すでに述べた名前を取得する1つの方法は、name属性を使用することです。

try:
    import pty
except ImportError as e:
    print(e.name)

ただし、可能性があるは、開始したモジュール名を取得できないことに注意することが重要です。つまり、上記をWindowsで実行すると、出力としてtermiosではなくptyが得られます。

python 2.7との互換性を維持するために(切り替えを行っていない人のために、あなたは 時計 にいます)

try:
    import pty
except ImportError as e:
    print(e.args[0].rsplit(' ',1)[-1])  # `msg` attribute is `message` on python2...stick with args

# prints the same result: termios

  • Python 3.6は2016年の終わり頃にリリースされました。2019年以降なので、より明確な例外ModuleNotFoundErrorを選択できます。

    モジュールが見つからなかったときにインポートによって発生するImportErrorのサブクラス。 sys.modulesでNoneが見つかった場合にも発生します。

  • Python 3.3+を使用している場合は、(すでに説明したpathに加えて)name属性を忘れないでください。これにより、例外を発生させたファイル(より複雑な場合にのみ役立ちます-私がpathに与えたような単純な例ではNoneを返します)。

3
YenForYang