85234


## 環境

Windows 10 Pro  
VSCode 1.63.0  
Python 3.9.6

## 現状

・VScodeでは例外が正常にキャッチできません。（以前はできていました。）  
・コマンドプロンプトでスクリプト直接実行すると正常に実行できます。  
・PyScripterでは正常に実行できます。  
・例にあげたスクリプト以外でも例外が正常にキャッチできません。

VScodeにおいて、デバッグ実行(F5)で実行する際に、例外が正常に機能しない状態で、デバッグなし実行では正常な結果を出力することから、該当する例外スロー部分は正常に機能しているという意味です。また、このような動作になったのは最近のことで、以前はこのような動作ではなく、デバッグ実行でも正常な結果でした。

venvによる仮想環境でのデバッグ実行で現象が発生することが分かりました。venvではない環境で同じバージョンのpythonによりデバッグ実行した場合には、正常に動作することが分かりました。

VScodeで正常に例外キャッチさせるにはどうしたらよいでしょうか？

## スクリプト

以下のpythonスクリプトを例として記述しますが、以前は正常に動作していたスクリプトです。  
アプリケーションから起動するサーバーのip address:portが既にOpenしているかを確認するものです。

`except socket.timeout` の部分で例外をキャッチして判断します。

以前は、この例外キャッチできてしました。

[code]

    #! /usr/bin/env python3
    # -*- coding: utf-8 -*-
    
    """ class_NetworkPort.py
    FileName:
    --------------------------------------------------------------------------------
        class_NetworkPort.py
    
    Description:
    --------------------------------------------------------------------------------
        ネットワークのポートをチェックします。
    
    History:
    --------------------------------------------------------------------------------
        2020/12/21 作成
    
    """
    
    import socket
    import ipaddress
    
    UDP = 'UDP'
    TCP = 'TCP'
    IPv4 = socket.AF_INET
    
    class class_NetworkPort():
        def __init__(self):
            """初期化　ソケットのタイムアウト値を設定します。
            """
            socket.setdefaulttimeout(1)
    
        def chk_address_port(self,ip_address:str,port_number:int):
            if not isinstance(port_number,int):
                return
            else:
                if port_number == 0 or port_number > 65535:
                    return
            if isinstance(ip_address,str):
                try:
                    _address_ = ipaddress.IPv4Address(ip_address)
                    if _address_ is not None:
                        if _address_.is_multicast \
                            or _address_.is_reserved \
                            or _address_.version != 4:
                            return
                    else:
                        return
    
                except ipaddress.AddressValueError:
                    return
            else:
                return
    
            return True
    
        def check_localhost(self,ip_address):
            """自機に割り振られたIPv4アドレスかどうかを確認します。
    
            Args:
                ip_address ([str]):IPv4アドレス文字列、マルチキャストや予約済みアドレスは禁止。
            Returns:
                [bool]: 自機アドレスならTrue
            """
    
            ip_list = list()
            host = socket.gethostname()
            hostname, _ , ip_list = socket.gethostbyname_ex(host)
    
            _,_,localhost = socket.gethostbyname_ex('localhost')
            ip_list.extend(localhost)
    
            if ip_address in ip_list:
                return True
    
            return False
    
        def check_bind_port(self,ip_address:str,protocol_type:str,port_number:int):
            """自機のPCにバインドできるポートであるか確認
    
            Args:
                ip_address (str):IPv4アドレス文字列、マルチキャストや予約済みアドレスは禁止。
                protocol_type (str): TCP/UDP
                port_number (int): ポート番号0以外の65535以下のポート番号
            Returns:
                [bool]: 変数の違反ならNone,バインドできなければFalse、バインド成功ならTrue
            """
    
            isOK = False
            if protocol_type != UDP and protocol_type != TCP:
                return
            else:
                if protocol_type == UDP:
                    _ptype_ = socket.SOCK_DGRAM
                if protocol_type == TCP:
                    _ptype_ = socket.SOCK_STREAM
    
            try:
                isOK = self.chk_address_port(ip_address,port_number,)
            except ipaddress.AddressValueError as e:
                raise e
    
            _chk_socket_ = socket.socket(IPv4,_ptype_)
    
            try:
                _chk_socket_.bind((ip_address,port_number))
                isOK = True
            except OSError:
                isOK = False
    
            _chk_socket_.close()
    
            return isOK
    
        def check_connect_port(self,ip_address:str,protocol_type:str,port_number:int):
            """接続先のTCPポートに接続できるかを確認。
    
            Args:
                ip_address (str):IPv4アドレス文字列、マルチキャストや予約済みアドレスは禁止。
                protocol_type (str): TCP
                port_number (int): ポート番号0以外の65535以下のポート番号
            Returns:
                [bool]: 変数の違反ならNone,接続できなければFalse、接続成功ならTrue
            """
    
            isOK = False
            if protocol_type != TCP:
                return
            else:
                if protocol_type == TCP:
                    _ptype_ = socket.SOCK_STREAM
            try:
                isOK = self.chk_address_port(ip_address,port_number,)
            except ipaddress.AddressValueError as e:
                raise e
    
            _chk_socket_ = socket.socket(IPv4,_ptype_)
    
            try:
                _chk_socket_.connect((ip_address,port_number))
                isOK = True
            except socket.timeout:
                isOK = False
            except OSError:
                isOK = False
    
            _chk_socket_.close()
    
            return isOK
    
    
    if __name__ == '__main__':
        instNW = class_NetworkPort()
    
        ip_address = '127.0.0.1'
        protocol_type = TCP
        port_number = [8080,6970]
    
        for i in port_number:
            if instNW.check_connect_port(
                ip_address = ip_address,
                protocol_type = protocol_type,
                port_number= i
                ):
                print('ソケット接続成功　{} {}:{}'.format(ip_address,protocol_type,i))
            else:
                print('XXXXソケット失敗XXXX　{} {}:{}'.format(ip_address,protocol_type,i))
    
    
        if instNW.check_localhost(ip_address=ip_address):
            for i in range(1024):
                if instNW.check_bind_port(
                    ip_address = ip_address,
                    protocol_type = protocol_type,
                    port_number= i
                    ):
                    print('バインド成功　{} {}:{}'.format(ip_address,protocol_type,i))
                else:
                    print('XXXXバインド失敗XXXX　{} {}:{}'.format(ip_address,protocol_type,i))
        else:
            for i in range(1024):
                if instNW.check_connect_port(
                    ip_address = ip_address,
                    protocol_type = protocol_type,
                    port_number= i
                    ):
                    print('ソケット接続成功　{} {}:{}'.format(ip_address,protocol_type,i))
                else:
                    print('XXXXソケット失敗XXXX　{} {}:{}'.format(ip_address,protocol_type,i))
    
    
[/code]

## VScode のエラー出力

現在のVScode上でのエラー出力は以下のようになります。

[code]

    例外が発生しました: timeout
    timed out
      File "C:\Users\ユーザー名\プロジェクトフォルダ\class_NetworkPort.py", line 139, in check_connect_port
        _chk_socket_.connect((ip_address,port_number))
      File "C:\Users\ユーザー名\プロジェクトフォルダ\class_NetworkPort.py", line 159, in <module>
        if instNW.check_connect_port(
    
[/code]

モジュール名socketが認識されていない？ようです。  
このため、  
except socket.timeout → except timeout  
としてみましたが、timeoutでは認識できませんでした。


CC BY-SA 4.0
2021-12-17T07:32:11.747
85194
2021-12-20T02:19:40.083
2021-12-20T00:43:42.470
3060
32891
question
python python3 vscode
VScodeで正常に例外がスローされなくなりました


自己解決したので記載します。

# 結論

VScodeを完全消去し、再度環境構築をした結果、正常になりました。  
VScodeの環境が何らかの影響で破壊されていた可能性が高いです。

# これまでの経緯

・cloneした別環境のPCでは正常に動作した。  
・以前に突如VScodeが起動しなくなり、完全消去ではない再インストールしたことがあった。  
・時折、VScode上でDELやBSキーが機能しなくなる現象があった。  
これらのことから、該当現象が発生しているPC上のVScodeのみで何らかの不具合があると想定。

# 完全消去

１）プログラムと機能からVScodeをアンインストールする。  
２）C:\Users\ユーザー名\AppData\Roaming\Codeのフォルダをフォルダ全体を削除  
３）C:\Users\ユーザー名.vscodeのフォルダをフォルダ全体を削除

# インストール

改めて、VScodeのインストーラでインストール  
VScode拡張機能をインストール  
※Python本体やpyenvなどの別途構築する環境は全く変更しておりません。


CC BY-SA 4.0
2021-12-20T02:19:40.083
85234
2021-12-20T02:19:40.083
32891
85194
answer