# User-defined exception

**URL:** <https://discuss.python.org/t/user-defined-exception/20704>\
**Category:** Python Help\
**Tags:** help\
**Created:** [November 3, 2022, 1:52pm UTC](https://discuss.python.org/t/user-defined-exception/20704 "2022-11-03T13:52:46Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![Pejamide](https://avatars.discourse-cdn.com/v4/letter/p/f07891/32.png) [@Pejamide](https://discuss.python.org/u/Pejamide)\
**Post date:** [November 3, 2022, 1:52pm UTC](https://discuss.python.org/t/user-defined-exception/20704/1 "2022-11-03T13:52:46Z")

</div>

I want to use a special exception, but I don’t know how to specify it for the following situation:  
My Python has several functions at several levels (i.e. by callings). I want to use the special exception at the second level (i.e. in the function which has been called by the function at the first (= root) level). In some functions from the second level I want to use the command ‘raise special-exception(code)’. In the function ‘special-exception(code)’ I want to look at the code. If the code is filled in, then the message must be written with the continuing after the lasting calling in the first level, else (i.e. code is not filled in) the wellknown traceback lines.

---

<div class="post-metadata">

**Author:** ![steven.daprano](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/steven.daprano/32/1083_2.png) [@steven.daprano](https://discuss.python.org/u/steven.daprano)\
**Post date:** [November 3, 2022, 8:20pm UTC](https://discuss.python.org/t/user-defined-exception/20704/2 "2022-11-03T20:20:36Z")

</div>

Sorry, I don’t understand your explanation of what you are trying to do.

> [@](#):
>
> I want to use the command ‘raise special-exception(code)’. In the function ‘special-exception(code)’ I want to look at the code. If the code is filled in,

What is `code`? What do you mean, “filled in”?

> [@](#):
>
> then the message must be written with the continuing after the lasting calling in the first level,

I don’t understand this.

Most importantly, why do you want to mess with the traceback?

Can you show an example of what you want?

```python
def spam():
    return eggs()

def eggs():
    # Second level, error happens here
    ...

spam()

```

Can you show us what traceback you want to see?

---

<div class="post-metadata">

**Author:** ![Pejamide](https://avatars.discourse-cdn.com/v4/letter/p/f07891/32.png) [@Pejamide](https://discuss.python.org/u/Pejamide)\
**Post date:** [November 4, 2022, 9:24am UTC](https://discuss.python.org/t/user-defined-exception/20704/3 "2022-11-04T09:24:39Z")

</div>

Well, I am trying to make it clear:

function1 calls function2 which calls funtion3.  
function3 contains (where \_ stands for space):

def function3(…):  
\_\_\_\_…  
\_\_\_\_…  
\_\_\_\_def MyException(code):  
\_\_\_\_\_\_\_\_import logging  
\_\_\_\_\_\_\_\_logging.error('Process MyException: ’ + str(code))  
\_\_\_\_\_\_\_\_# How to continue directly after the command '… = function4(…)?  
\_\_\_\_…  
\_\_\_\_…  
\_\_\_\_… = function4(…)  
\_\_\_\_…  
\_\_\_\_…  
\_\_\_\_return …

function4 calls function5 which calls funtion6.  
function6 contains (where \_ stands for space):

def function6(…):  
\_\_\_\_import logging  
\_\_\_\_…  
\_\_\_\_…  
\_\_\_\_if …:  
\_\_\_\_\_\_\_\_raise MyException(…):  
\_\_\_\_\_\_\_\_logging.error('Call MyException(123)  
\_\_\_\_…  
\_\_\_\_…  
\_\_\_\_xxx = 7 / 0  
\_\_\_\_# which will given a list of tracebacks like:  
\_\_\_\_# \<class ‘ZeroDivisionError’\>: division by zero  
\_\_\_\_# File “…”, line …, in function4: xxx = 7 / 0  
\_\_\_\_# File “…”, line …, in function3: …  
\_\_\_\_# File “…”, line …, in function2: …  
\_\_\_\_# File “…”, line …, in function1: …  
\_\_\_\_…  
\_\_\_\_…  
\_\_\_\_return …

Hopefully it is clear enough for you.  
an please tell me how I can create such a block without using \_\_\_\_.

---

<div class="post-metadata">

**Author:** ![vbrozik](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/vbrozik/32/7423_2.png) [@vbrozik](https://discuss.python.org/u/vbrozik)\
**Post date:** [November 4, 2022, 10:36am UTC](https://discuss.python.org/t/user-defined-exception/20704/4 "2022-11-04T10:36:45Z")

</div>

> [@Pejamide](#):
>
> please tell me how I can create such a block without using \_\_\_\_.

> [@Python Discourse Quick Start](https://discuss.python.org/t/python-discourse-quick-start/116#how-do-i-post-code-snippets-error-messages-etc-4):
>
> Python Discourse Help [About](https://discuss.python.org/about)[FAQ](https://discuss.python.org/faq) Keyboard Shortcuts Found in top right “hamburger” menu or press ? How do I bookmark a message? If one clicks the … icon below a message, it is replaced by a flag white_flag and bookmark icons. (The latter looks like a hanging banner, but represents the exposed end of a fabric bookmark.) (Silly to have to do this, but that is another topic.) In any case, click your profile image and the left of the three icons underneath is the bookmark icon. Click that you …

Please edit your post to show the code properly.

---

<div class="post-metadata">

**Author:** ![Pejamide](https://avatars.discourse-cdn.com/v4/letter/p/f07891/32.png) [@Pejamide](https://discuss.python.org/u/Pejamide)\
**Post date:** [November 7, 2022, 8:19pm UTC](https://discuss.python.org/t/user-defined-exception/20704/5 "2022-11-07T20:19:48Z")

</div>

I need the solution for the following example:

function1 calls function2 which calls funtion3.  
function3 contains:

```auto
def function3(…):
    import logging
    ...
    ...
    class MySpecialException(???):
        logging.error('MySpecialException is created.')
      
    ...
    ...
    try:
        result = function4(…)
    exception MySpecialException as e:
        if e == '123':
            logging.error('MySpecialException has been processed ' \\ 
                                 'with code * + str(e) + '*')
            # it must be continued after this try section
        else:
            # here a list of tracebacks must be created like:
            # File “…”, line …, in function5: …
            # File “…”, line …, in function4: …
            # File “…”, line …, in function3: …
            # File “…”, line …, in function2: …
            # File “…”, line …, in function1: …
            raise (which exception?) in order to end this procedure abnormally
    ...
    ...
    return

```

function4 calls function5 which calls funtion6.  
function6 contains:

```auto
def function6(…):
    import logging
    ...
    ...
    if ... :
        logging.error('MySpecialException(123) is called')
        raise MySpecialException(123)
    ...
    ...
    _ = 7 / 0
    # which must give a list of tracebacks like:
    # <class ‘ZeroDivisionError’>: division by zero
    # File “…”, line …, in function6: _ = 7 / 0
    # File “…”, line …, in function5: …
    # File “…”, line …, in function4: …
    # File “…”, line …, in function3: …
    # File “…”, line …, in function2: …
    # File “…”, line …, in function1: …
    ...
    ...
    return

```

Hopefully is this example clear for you in order to be able to give me any suggestion to make it possible.

---

<div class="post-metadata">

**Author:** ![Mholscher](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/mholscher/32/15325_2.png) [@Mholscher](https://discuss.python.org/u/Mholscher)\
**Post date:** [November 7, 2022, 10:14pm UTC](https://discuss.python.org/t/user-defined-exception/20704/6 "2022-11-07T22:14:25Z")

</div>

> [@Pejamide](#):
>
> ```auto
> def function3(…):
> import logging
> ...
> ...
> class MySpecialException(???):
> logging.error('MySpecialException is created.')
> 
> ```

Exceptions are ordinary classes, obeying the rules of definition.

```python
>>> def fun1():
... class MyException(Exception):
... pass
... raise MyException("It happened")
... 
>>> try:
... fun1()
... except MyException:
... print("Caught")
... 
Traceback (most recent call last):
  File "<input>", line 3, in <module>
    except MyException:
NameError: name 'MyException' is not defined

```

So, unless you want to use exceptions only locally, define your exceptions as global to your module.

Lets continue the session in the REPL:

```python
>>> class MyException(ValueError):
... pass
... 
>>> def fun6():
... raise MyException("It happened")
... 
>>> def fun5():
... fun6()
... return 1
... 
>>> def fun4():
... try:
... fun5()
... except MyException as me:
... print("Caught")
... raise
... 
>>> fun4()
Caught
Traceback (most recent call last):
  File "<input>", line 1, in <module>
    fun4()
  File "<input>", line 3, in fun4
    fun5()
  File "<input>", line 2, in fun5
    fun6()
  File "<input>", line 2, in fun6
    raise MyException("It happened")
MyException: It happened

```

This is about what you want, but for the code. I will come back to that.

- The `MyException` class now inherits from `ValueError`, which is [a child of Exception](https://docs.python.org/3/library/exceptions.html?highlight=exception#exception-hierarchy). Will work also and catching ValueError will also catch MyException

- The traceback (yes, it is only 1 traceback that shows all steps) shows exactly what was called. I printed it by raising it again, it is easy. You can access is also through the ` __traceback__ ` attribute: [“A traceback object is normally created automatically when an exception is raised and attached to it as the ` __traceback__ ` attribute, which is writable.”](https://docs.python.org/3/reference/simple_stmts.html#the-raise-statement).

I would never pass a code to identify what type of exception is raised. Always define multiple exception subclasses and switch between exceptions by type. The syntax makes that easy and your code clearer.

---

<div class="post-metadata">

**Author:** ![Rosuav](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/rosuav/32/3429_2.png) [@Rosuav](https://discuss.python.org/u/Rosuav)\
**Post date:** [November 7, 2022, 10:36pm UTC](https://discuss.python.org/t/user-defined-exception/20704/7 "2022-11-07T22:36:02Z")

</div>

> [@Mholscher](#):
>
> I would never pass a code to identify what type of exception is raised.

Unless the code came from elsewhere (OSError incorporates the OS-provided error code).

---

<div class="post-metadata">

**Author:** ![Mholscher](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/mholscher/32/15325_2.png) [@Mholscher](https://discuss.python.org/u/Mholscher)\
**Post date:** [November 8, 2022, 10:57am UTC](https://discuss.python.org/t/user-defined-exception/20704/8 "2022-11-08T10:57:44Z")

</div>

Thank you for supplying an excellent example of what I mean. You could usually identify an OSError by the OS supplied error number, yet it has several subclasses that make the client code easier and clearer. Of course the error number should be kept by the subclasses, so you can always dig deeper.

@Pejamide : What is discussed here is this part of the exception hierarchy:

```auto
     ├── OSError
      │ ├── BlockingIOError
      │ ├── ChildProcessError
      │ ├── ConnectionError
      │ │ ├── BrokenPipeError
      │ │ ├── ConnectionAbortedError
      │ │ ├── ConnectionRefusedError
      │ │ └── ConnectionResetError
      │ ├── FileExistsError
      │ ├── FileNotFoundError
      │ ├── InterruptedError
      │ ├── IsADirectoryError
      │ ├── NotADirectoryError
      │ ├── PermissionError
      │ ├── ProcessLookupError
      │ └── TimeoutError

```

Most of those errors could be identified by the `OSError.errno` attribute:  
“The constructor often actually returns a subclass of [`OSError`](https://docs.python.org/3/library/exceptions.html?highlight=oserror#OSError), as described in [OS exceptions](https://docs.python.org/3/library/exceptions.html?highlight=oserror#os-exceptions) below. The particular subclass depends on the final [`errno`](https://docs.python.org/3/library/exceptions.html?highlight=oserror#OSError.errno) value.”

Yet, they are distinguished by type to enable you to write easier to understand and clearer code.

```auto
>>> try:
... f = open("/usr/local/nofile", "r")
... except FileNotFoundError:
... print("Caught")
... 
Caught

```

---

<div class="post-metadata">

**Author:** ![Pejamide](https://avatars.discourse-cdn.com/v4/letter/p/f07891/32.png) [@Pejamide](https://discuss.python.org/u/Pejamide)\
**Post date:** [November 13, 2022, 2:49pm UTC](https://discuss.python.org/t/user-defined-exception/20704/9 "2022-11-13T14:49:25Z")

</div>

I tried as follows:

```auto
...
...
def MySpecialExecption(PermissionError):
    pass
...
...
try:
    ...
    ...
except MySpecialExecption as e:
    print('MySpecialExecption has been exceuted here.')
    print(e)
...
...

```

But I got the message as follows:

```auto
<class 'TypeError'>: catching classes that do not inherit from BaseException is not allowed

```

What to do now?

---

<div class="post-metadata">

**Author:** ![Mholscher](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/mholscher/32/15325_2.png) [@Mholscher](https://discuss.python.org/u/Mholscher)\
**Post date:** [November 13, 2022, 3:14pm UTC](https://discuss.python.org/t/user-defined-exception/20704/10 "2022-11-13T15:14:34Z")

</div>

An exception is a class, not a function. Functions do not inherit from BaseException.

```auto
>>> def MyException(PermissionError):
... pass
... 
>>> try:
... raise MyException("Oops!")
... except MyException as me:
... print(me)
... 
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
TypeError: exceptions must derive from BaseException

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 3, in <module>
TypeError: catching classes that do not inherit from BaseException is not allowed
>>> class MyException(PermissionError):
... pass
... 
>>> try:
... raise MyException("Oops!")
... except MyException as me:
... print(me)
... 
Oops!

```

---

<div class="post-metadata">

**Author:** ![Pejamide](https://avatars.discourse-cdn.com/v4/letter/p/f07891/32.png) [@Pejamide](https://discuss.python.org/u/Pejamide)\
**Post date:** [November 14, 2022, 7:51pm UTC](https://discuss.python.org/t/user-defined-exception/20704/11 "2022-11-14T19:51:40Z")

</div>

I have specified in the function ‘fn3’:

```auto
class MyException(PermissionError):
    pass

```

And the function ‘fn6’ which is called by fn5, fn4 and fn3 resp.:

```auto
raise MyException(123)

```

But I got the folloeing error message:  
\<class ‘NameError’\>: name ‘ExecptionForReentry’ is not defined

What have i to do yet?

---

<div class="post-metadata">

**Author:** ![Mholscher](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/mholscher/32/15325_2.png) [@Mholscher](https://discuss.python.org/u/Mholscher)\
**Post date:** [November 14, 2022, 9:13pm UTC](https://discuss.python.org/t/user-defined-exception/20704/12 "2022-11-14T21:13:11Z")

</div>

> [@Pejamide](#):
>
> What have i to do yet?

I don’t know. There must be something else going wrong. This works:

```python
>>> class MyException(PermissionError):
... pass
... 
>>> raise MyException(123)
Traceback (most recent call last):
  File "<input>", line 1, in <module>
    raise MyException(123)
MyException: 123

```

So your original problem is solved. _Where_ in your code does this error come up? You can find that in the traceback. If you want more help, show the traceback,

Also observe that the reported error is a [NameError](https://docs.python.org/3/library/exceptions.html?highlight=oserror#NameError). What is causing that `NameError`? Also to be found in the traceback.

---

<div class="post-metadata">

**Author:** ![Pejamide](https://avatars.discourse-cdn.com/v4/letter/p/f07891/32.png) [@Pejamide](https://discuss.python.org/u/Pejamide)\
**Post date:** [November 16, 2022, 3:51pm UTC](https://discuss.python.org/t/user-defined-exception/20704/13 "2022-11-16T15:51:59Z")

</div>

I’m very sorry for my previous unclear question.  
Hence my corrected question.

The function ‘fn3’ which is called by the functions ‘fn1’ and ‘fn2’ respectively, contains:

```auto
...
...
class MyException(PermissionError):
    pass
...
...

```

And the function ‘fn6’ which is called by fn5, fn4 and fn3 respectively. It contains:

```auto
...
...
raise MyException(123)
...
...

```

But I got the following error message:  
\<class ‘NameError’\>: name ‘MyException’ is not defined  
with tracebacks:

```auto
<class 'NameError'>: name 'MyException' is not defined called by File "fn6.py", line 52, in fn6: raise MyException(123)
... called by File "fn5.py", line 116, in fn5: .......
... called by File "fn4.py", line 100, in fn4: .......
... called by File "fn3.py", line 506, in fn3: .......

```

Unfortunately I d’not know how to specify each function for your test, as I am using the command ‘importlib.import\_module’ for two functions ‘fn3’ and ‘fn6’.

What should I have to do extra?

---

<div class="post-metadata">

**Author:** ![cameron](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/cameron/32/2658_2.png) [@cameron](https://discuss.python.org/u/cameron)\
**Post date:** [November 16, 2022, 11:35pm UTC](https://discuss.python.org/t/user-defined-exception/20704/14 "2022-11-16T23:35:37Z")

</div>

> I’m very sorry for my previous unclear question.  
> Hence my corrected question.
> 
> The function ‘fn3’ which is called by the functions ‘fn1’ and ‘fn2’ respectively, contains:
> 
> ```auto
> class MyException(PermissionError):
> pass
> 
> ```

Look good.

> And the function ‘fn6’ which is called by fn5, fn4 and fn3 respectively. It contains:
> 
> ```auto
> raise MyException(123)
> 
> ```

Looks good.

> But I got the following error message:  
> \<class ‘NameError’\>: name ‘MyException’ is not defined  
> with tracebacks:  
> \<class ‘NameError’\>: name ‘MyException’ is not defined called by File “fn6.py”, line 52, in fn6: raise MyException(123)  
> … called by File “fn5.py”, line 116, in fn5: …  
> … called by File “fn4.py”, line 100, in fn4: …  
> … called by File “fn3.py”, line 506, in fn3: …
> 
> ```auto
> Unfortunately I d'not know how to specify each function for your test, as I am using the command 'importlib.import_module' for two functions 'fn3' and 'fn6'.
> 
> What should I have to do extra?
> 
> ```

It looks like your functions are all defined in separate files. (Is  
there a reason for that?) Thus the name `fn5` is _initially_ only known  
in the code in the file `fn5.py` and so forth.

Because of this separate, you’re importing the names of functions to  
make them known in the code which uses them, eg something like:

```
 from fn5 import fn5

```

It looks like you have defined `MyException` in the `fn3.py` file? Like  
the `fn3` function, you need to import the name `MyException` to use it  
elsewhere. So if the file `fn6.py` from the traceback has a line like:

```
 from fn3 import fn3

```

that needs to be extended like:

```
 from fn3 import fn3, MyException

```

so that the name `MyException` is also known.

Cheers,  
Cameron Simpson [cs@cskk.id.au](mailto:cs@cskk.id.au)

---

<div class="post-metadata">

**Author:** ![Pejamide](https://avatars.discourse-cdn.com/v4/letter/p/f07891/32.png) [@Pejamide](https://discuss.python.org/u/Pejamide)\
**Post date:** [November 17, 2022, 9:10am UTC](https://discuss.python.org/t/user-defined-exception/20704/15 "2022-11-17T09:10:22Z")

</div>

My system saves all addresses of imported modules in the table. In this case my system can get the address of the specific function there for processing.

Concerning your simple solution, all my functions ‘fn…’ are imported via the special function ‘importlib.import\_module’. In this case I cannot use your simple solution ‘from fn3 import MyException’. That does give the error:  
\<class ‘ModuleNotFoundError’\>: No module named ‘fn3’.

What to do now?

---

<div class="post-metadata">

**Author:** ![cameron](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/cameron/32/2658_2.png) [@cameron](https://discuss.python.org/u/cameron)\
**Post date:** [November 17, 2022, 9:24pm UTC](https://discuss.python.org/t/user-defined-exception/20704/16 "2022-11-17T21:24:21Z")

</div>

Whatever incantation you’re using with `importlib` to import, say `fn3`,  
you need to use to import `MyException`. If you’ve imported the module  
containing the `MyException` definition, let us call that module `M`,  
then you can access the exception as `M.MyException`. Or you can put  
this:

```
 MyException = M.MyException

```

and just use `MyException` from then on. That’s effective what the `from M import MyException` statement does anyway.

Cheers,  
Cameron Simpson [cs@cskk.id.au](mailto:cs@cskk.id.au)

---

<div class="post-metadata">

**Author:** ![Pejamide](https://avatars.discourse-cdn.com/v4/letter/p/f07891/32.png) [@Pejamide](https://discuss.python.org/u/Pejamide)\
**Post date:** [November 22, 2022, 9:15am UTC](https://discuss.python.org/t/user-defined-exception/20704/17 "2022-11-22T09:15:51Z")

</div>

In order to import a function from the specified map, I use the following commands for needed functions ‘function…’:

```auto
functionData = importlib.import_module('......./......./function...')
returncode = getattr(functionData, 'function...')('aaa', 'bbb', 'ccc')

```

Is there better solution for this the cumbersome routine?

Now I wonder whether I can import MyException in the function ‘function6’ as the following command?

```auto
MyException = function3.MyException

```

---

<div class="post-metadata">

**Author:** ![Mholscher](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/mholscher/32/15325_2.png) [@Mholscher](https://discuss.python.org/u/Mholscher)\
**Post date:** [November 23, 2022, 2:02pm UTC](https://discuss.python.org/t/user-defined-exception/20704/18 "2022-11-23T14:02:54Z")

</div>

> [@Pejamide](#):
>
> Is there better solution for this the cumbersome routine?

Certainly, the [`import`](https://docs.python.org/3/reference/simple_stmts.html#the-import-statement) statement.

However, in order to find the module or package, your files need to be in a place where the default finder will find them.

> [@Pejamide](#):
>
> Now I wonder whether I can import MyException in the function ‘function6’ as the following command?
> 
> `MyException = function3.MyException`

No, but `import MyException from function3` will work. @cameron mentioned this previously.

Your `function3` module needs to be in the paths the default finder looks. I.e. in the current directory, in the site packages (where things installed using pip are placed) or in the standard library.

---

<div class="post-metadata">

**Author:** ![Pejamide](https://avatars.discourse-cdn.com/v4/letter/p/f07891/32.png) [@Pejamide](https://discuss.python.org/u/Pejamide)\
**Post date:** [November 25, 2022, 2:40pm UTC](https://discuss.python.org/t/user-defined-exception/20704/19 "2022-11-25T14:40:24Z")

</div>

My program ‘fn3’ contains:

```auto
.......
sys.path.insert(0, 'D:/Server/PythonNew/bsx/pyx')
sys.path.insert(0, 'D:/Server/PythonNew/prd/pyx')
sys.path.insert(0, 'D:/Server/PythonNew/tst/pyx')
logging.error('-Test fn3 1-')
from fn4 import fn4
logging.error('-Test fn3 2-')
fn4(.......)
logging.error('-Test fn3 3-')
.......

```

My program ‘fn4’ contains:

```auto
.......
class MyException(PermissionError):
  logging.error('MyException classed!')
.......
logging.error('-Test fn4 1-')
from fn5 import fn5
logging.error('-Test fn4 2-')
fn5(.......)
logging.error('-Test fn4 3-')
.......

```

My program ‘fn5’ contains:

```auto
.......
logging.error('-Test fn5 1-')
from fn4 import MyException
logging.error('-Test fn5 2-')
MyException = fn4.MyException
logging.error('-Test fn5 3-')
.......

```

The line ‘from fn4 import MyException’ gives error:  
\<class ‘ImportError’\>: cannot import name ‘MyException’ from fn4’.

Without the line ‘from fn4 import MyException’, the line ‘MyException = fn4.MyException’ gives error:  
\<class ‘NameError’\>: name ‘fn4’ is not defined.

What should one or more abovementioned programs to be corrected?

---

<div class="post-metadata">

**Author:** ![cameron](https://sea2.discourse-cdn.com/flex002/user_avatar/discuss.python.org/cameron/32/2658_2.png) [@cameron](https://discuss.python.org/u/cameron)\
**Post date:** [November 25, 2022, 9:13pm UTC](https://discuss.python.org/t/user-defined-exception/20704/20 "2022-11-25T21:13:42Z")

</div>

> My program ‘fn3’ contains:
> 
> ```auto
> sys.path.insert(0, 'D:/Server/PythonNew/bsx/pyx')
> sys.path.insert(0, 'D:/Server/PythonNew/prd/pyx')
> sys.path.insert(0, 'D:/Server/PythonNew/tst/pyx')
> 
> ```

Ah, you’re adjusting the import path. Good!

> ```auto
> from fn4 import fn4
> fn4(.......)
> 
> ```
> 
> My program ‘fn4’ contains:
> 
> ```auto
> class MyException(PermissionError):
> logging.error('MyException classed!')
> .......
> from fn5 import fn5
> fn5(.......)
> 
> ```
> 
> My program ‘fn5’ contains:
> 
> ```auto
> logging.error('-Test fn5 1-')
> from fn4 import MyException
> 
> ```
> 
> The line ‘from fn4 import MyException’ gives error:  
> \<class ‘ImportError’\>: cannot import name ‘MyException’ from fn4’.

Please transcribe the _entire_ message. Usually this one contains more  
information.

This issue arises because you have a circular import. `fn3` imports  
`fn4` imports `fn5` imports `fn4`.

When you import files, they are _run_! An `import` statement does not  
return until the file it is importing has run to completion. So a  
circular import cannot complete - because an “in progress” import is  
still in progress. If it was just run naively you would get a Python  
recursion error as the modules imported each other in a loop.

The import machinery knows that the import of `fn4` is still in progress  
during the import of `fn3`. So when `fn4`’s import runs, importing `fn5`  
,and then `fn5`’s import tries to import `fn4`, the import machinery  
raises this exception because `fn4` has not completed.

> Without the line ‘from fn4 import MyException’, the line ‘MyException = fn4.MyException’ gives error:  
> \<class ‘NameError’\>: name ‘fn4’ is not defined.

Yes, you’ll need the `import` to define the name, (It would be no  
different with your previous methods using the `importlib` module - the  
`import` statement just runs that stuff conveniently and reliably for  
you).

> What should one or more abovementioned programs to be corrected?

The import chain you have looks like this ASCII diagram:

```
 fn3 -> fn4 -> fn5 -+
         ^ |

```

[Next page](https://discuss.python.org/t/user-defined-exception/20704.md?page=2)
