I've recently started programming in Python and I've decided to code some Delphi functions in Python. I've decided to create a single Python module that holds my functions.
Now, I tried to import it, but I get this error in Visual Studio Code:
unable to import 'functions' pylint(import error) [5, 1]
Here is my code:
import sys
sys.path.append('/Users/user123/Desktop/Python/Functions/')
import functions
Here is an image:
The simplest example would be:
.
├── functions
│ ├── functions.py
└── main
└── main.py
Now in the functions/functions.py
I have:
from datetime import datetime
def print_datetime():
print(datetime.utcnow())
and in main/main.py
I have:
import sys
sys.path.append(".")
from functions.functions import print_datetime
if __name__ == '__main__':
print_datetime()
This sys.path.append(".")
is helping you to switch the context from where you are calling the main.py
, to be more accurate it adds higher directory to python modules path.
And while you are in the top-level directory of the project, you can now run the main.py
which will produce a result like this:
(venv) user@pc: .../59702230
$ python main/main.py
2020-01-12 09:51:01.469436
For more details on how to do this, you can read a great QA in the beyond top level package error in relative import where is a lot of great information on how to solve the same issue with different approaches.
I hope that it will help you!
Given your file/folder structure:
├── Functions
│ └── functions.py
├── <main app folder>
│ └── app.py
Although your imports may run correctly once you've added path/to/Functions
to sys.path
, Pylint is giving you that warning because that is not the recommended way of declaring imports, especially when you're importing modules outside the app package/folder.
From the PEP8 Style Guide for Imports:
Absolute imports are recommended, as they are usually more readable and tend to be better behaved (or at least give better error messages) if the import system is incorrectly configured (such as when a directory inside a package ends up on
sys.path
):import mypkg.sibling from mypkg import sibling from mypkg.sibling import example
The recommended solution is to setup Functions
as a package by adding a __init__.py
file under it:
├── parent
│ └── Functions
│ ├── __init__.py
│ └── functions.py
then importing your functions like one of these:
sys.path.append("/path/to/parent")
# option 1
from Functions import functions
functions.copy()
functions.delete()
# option2
from Functions.functions import copy, delete
copy()
delete()
Both options should run correctly and satisfy PyLint.
Now, if you really want to do a non-absolute import like from functions import func
, and get PyLint to accept that, I recommend renaming functions.py
to something else. This is because, on some case-insensitive systems, importing Functions
and functions
could get treated as the same module. When you tell PyLint to look into /path/to/Functions
(I'll show later), it might not be able to differentiate if copy
and delete
is part of Functions
or of functions
, and it might still show an import-error.
So, what you need to do is rename functions.py
(ex. filefuncs.py
):
├── Functions
│ └── filefuncs.py
├── <main app folder>
│ └── app.py
Then in you VS Code workspace, add this to your .vscode/settings.json file to tell PyLint where to look for the filefuncs
module:
"python.linting.pylintArgs": [
"--init-hook",
"import sys; sys.path.append('/path/to/Functions')"
]
Then you can now import it same as your original code but without PyLint errors:
sys.path.append("/path/to/Functions")
from filefuncs import copy, delete
copy()
delete()
The second way will get you what you need, but it contains some workarounds for PyLint to work. If you can use the recommended way I explained at the start, use that instead.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With