Repository: pylint-dev/pylint

Issue:
`used-before-assignment` FP in finally
### Bug description

```python
# pylint: disable=missing-module-docstring,missing-function-docstring,bare-except
def good():
    try:
        status = 1
    except:
        status = 2
    finally:
        print(status)
```


### Configuration

_No response_

### Command used

```shell
pylint a.py
```


### Pylint output

```python
a.py:7:14: E0601: Using variable 'status' before assignment (used-before-assignment)
```


### Expected behavior

no msg

### Pylint version

```shell
pylint 3.1.0-dev0
astroid 3.1.0-dev0
Python 3.12.1 (v3.12.1:2305ca5144, Dec  7 2023, 17:23:38) [Clang 13.0.0 (clang-1300.0.29.30)]
```


### OS / Environment

_No response_

### Additional dependencies

_No response_


Discussion:

Patch:
diff --git a/doc/whatsnew/fragments/9451.false_positive b/doc/whatsnew/fragments/9451.false_positive
new file mode 100644
index 0000000000..ea2045f91d
--- /dev/null
+++ b/doc/whatsnew/fragments/9451.false_positive
@@ -0,0 +1,4 @@
+Fix false positive for ``used-before-assignment`` in a ``finally`` block
+when assignments took place in both the ``try`` block and each exception handler.
+
+Closes #9451
diff --git a/pylint/checkers/variables.py b/pylint/checkers/variables.py
index bc20d1987e..e38bec03e3 100644
--- a/pylint/checkers/variables.py
+++ b/pylint/checkers/variables.py
@@ -667,7 +667,7 @@ def get_next_to_consume(self, node: nodes.Name) -> list[nodes.NodeNG] | None:
         if found_nodes:
             uncertain_nodes = (
                 self._uncertain_nodes_in_try_blocks_when_evaluating_finally_blocks(
-                    found_nodes, node_statement
+                    found_nodes, node_statement, name
                 )
             )
             self.consumed_uncertain[node.name] += uncertain_nodes
@@ -1140,7 +1140,9 @@ def _uncertain_nodes_in_try_blocks_when_evaluating_except_blocks(
 
     @staticmethod
     def _uncertain_nodes_in_try_blocks_when_evaluating_finally_blocks(
-        found_nodes: list[nodes.NodeNG], node_statement: _base_nodes.Statement
+        found_nodes: list[nodes.NodeNG],
+        node_statement: _base_nodes.Statement,
+        name: str,
     ) -> list[nodes.NodeNG]:
         uncertain_nodes: list[nodes.NodeNG] = []
         (
@@ -1187,6 +1189,12 @@ def _uncertain_nodes_in_try_blocks_when_evaluating_finally_blocks(
                 )
             ):
                 continue
+            # Is the name defined in all exception clauses?
+            if other_node_try_finally_ancestor.handlers and all(
+                NamesConsumer._defines_name_raises_or_returns_recursive(name, handler)
+                for handler in other_node_try_finally_ancestor.handlers
+            ):
+                continue
             # Passed all tests for uncertain execution
             uncertain_nodes.append(other_node)
         return uncertain_nodes


Test patch:
diff --git a/tests/functional/u/used/used_before_assignment_issue85.py b/tests/functional/u/used/used_before_assignment_issue85.py
index 7ede436bb9..218dad9d00 100644
--- a/tests/functional/u/used/used_before_assignment_issue85.py
+++ b/tests/functional/u/used/used_before_assignment_issue85.py
@@ -34,6 +34,16 @@ def try_except_finally_assignment_in_final_block():
     print(res)
 
 
+def try_except_finally_assignment_in_both_try_and_except():
+    """Assignment of the name in both try and except blocks is fine."""
+    try:
+        res = 1 / 0
+    except ZeroDivisionError:
+        res = 0
+    finally:
+        print(res)
+
+
 def try_except_finally_nested_try_finally_in_try():
     """Don't confuse assignments in different finally statements where
     one is nested inside a try.
diff --git a/tests/functional/u/used/used_before_assignment_issue85.txt b/tests/functional/u/used/used_before_assignment_issue85.txt
index 9f405c2c5c..d7d002d75e 100644
--- a/tests/functional/u/used/used_before_assignment_issue85.txt
+++ b/tests/functional/u/used/used_before_assignment_issue85.txt
@@ -1,10 +1,10 @@
 used-before-assignment:8:14:8:17:main:Using variable 'res' before assignment:CONTROL_FLOW
 used-before-assignment:20:14:20:17:try_except_finally:Using variable 'res' before assignment:CONTROL_FLOW
-used-before-assignment:45:18:45:21:try_except_finally_nested_try_finally_in_try:Using variable 'res' before assignment:HIGH
-used-before-assignment:70:18:70:29:try_except_finally_nested_in_finally:Using variable 'outer_times' before assignment:CONTROL_FLOW
-used-before-assignment:84:18:84:29:try_except_finally_nested_in_finally_2:Using variable 'inner_times' before assignment:CONTROL_FLOW
-used-before-assignment:85:14:85:25:try_except_finally_nested_in_finally_2:Using variable 'outer_times' before assignment:CONTROL_FLOW
-used-before-assignment:100:18:100:29:try_except_finally_nested_in_finally_3:Using variable 'inner_times' before assignment:CONTROL_FLOW
-used-before-assignment:101:18:101:29:try_except_finally_nested_in_finally_3:Using variable 'outer_times' before assignment:CONTROL_FLOW
-used-before-assignment:122:22:122:33:try_except_finally_nested_in_finally_4:Using variable 'inner_times' before assignment:CONTROL_FLOW
-used-before-assignment:123:22:123:33:try_except_finally_nested_in_finally_4:Using variable 'outer_times' before assignment:CONTROL_FLOW
+used-before-assignment:55:18:55:21:try_except_finally_nested_try_finally_in_try:Using variable 'res' before assignment:HIGH
+used-before-assignment:80:18:80:29:try_except_finally_nested_in_finally:Using variable 'outer_times' before assignment:CONTROL_FLOW
+used-before-assignment:94:18:94:29:try_except_finally_nested_in_finally_2:Using variable 'inner_times' before assignment:CONTROL_FLOW
+used-before-assignment:95:14:95:25:try_except_finally_nested_in_finally_2:Using variable 'outer_times' before assignment:CONTROL_FLOW
+used-before-assignment:110:18:110:29:try_except_finally_nested_in_finally_3:Using variable 'inner_times' before assignment:CONTROL_FLOW
+used-before-assignment:111:18:111:29:try_except_finally_nested_in_finally_3:Using variable 'outer_times' before assignment:CONTROL_FLOW
+used-before-assignment:132:22:132:33:try_except_finally_nested_in_finally_4:Using variable 'inner_times' before assignment:CONTROL_FLOW
+used-before-assignment:133:22:133:33:try_except_finally_nested_in_finally_4:Using variable 'outer_times' before assignment:CONTROL_FLOW