I have the following repository structure
root
-code
--main.py
--helper.py
When I deploy a service, I use the following InferenceConfig, from the root level:
inference_config = InferenceConfig(entry_script='code/main.py',
source_directory='.',
environment=environment)
Running everything locally works fine. Even from the command line as python code/main.py. However, as soon as I deploy it as a service I get an ModuleNotFoundError, because the main.py can't find/import the helper (currently done via simple import helper).
I have tried both of these workarounds with no luck:
__init__.py to the /code What is the right approach to relative module imports in AML, when the deployment is done from the root repository folder and additional modules are in sub-folders?
Here a hacky work-around, adding this to the top of your main.py:
import os, sys; sys.path.append(os.path.dirname(os.path.realpath(__file__)))
Further looking into this, i saw that the current working directory ( os.getcwd() ) points to : /var/azureml-app/
This causes issues when trying to load things from the repository, as it is not the same behavior when running the code locally. For example, when trying to retrieve a file from /var/azureml-app/repo-name/assets.
Why is os.getcwd() != /var/azureml-app/repo-name/ ?
@vaidya-s
@Bozhong68
@maknotavailable you can change inference_config to following to make it work:
inference_config = InferenceConfig(entry_script='main.py',
source_directory='code',
environment=environment)
@maknotavailable thanks. I am experiencing the same problem. I don't understand from where we would execute your code. If you use main.py as the entry_script it means you would be inside the code directory? Then source_directory should be .code and not code?
Why is
os.getcwd() != /var/azureml-app/repo-name/
In the upcoming SDK release, the current working directory will be changed to the source directory; if one was given in the inference config.
@maknotavailable
I have tried both of these workarounds with no luck:
before the import, add sys.path.append('./code')
add __init__.py to the /code
The problem is that the current working directory (in the current AzureML SDK) is set to the directory above the source directory. So add sys.path.append('./code') wouldn't have worked because it would have needed to be add sys.path.append('./<source_directory_name>/code'). And add __init__.py to the /code doesn't work because it just allows for you do import code and treat the directory as a module.
The fix for this currently is to follow https://docs.microsoft.com/en-us/azure/machine-learning/how-to-deploy-and-where?tabs=azcli#define-an-entry-script . Specifically:
# If your model were stored in the same directory as your score.py, you could also use the following:
# model_path = os.path.abspath(os.path.join(os.path.dirname(__file__), 'sklearn_mnist_model.pkl')
In @maknotavailable 's situation, this would be (this will work in the current SDK and future releases):
import sys
# add code directory to sys path
sys.path.append(os.path.abspath(os.path.dirname(__file__)))
# should be able to import helper.py in code directory
import helper
after the next SDK release, this should be possible:
from code import helper
@jonringer for providing explanation and solution! @maknotavailable , @Konstantina-Lazaridou I will close the issue now, please feel free to re-open if you still have issues.
I'm trying to accomplish pretty much a similar thing, with one change that i have relative imports in my files.
Due to relative imports, scoring file fails with an error:
ImportError: attempted relative import with no known parent package
iles\modules structure (a simplified version):
project
->src
-> scoring.py
-> module1.py
-> common
-> module2.py, etc
-> init.py
-> init.py
-> configs
-> conda_env.yml
In scoring.py,
from .module1.py import SomeClass
..
..
In module1.py,
from .common.module2.py importSC2
...
..
And below is how an Inference config is initialized:
inference_config = InferenceConfig(source_directory="./",
runtime= "python",
entry_script="src/scoring.py",
conda_file="configs/conda_env.yml"
)
I could not pass entry_script as "src.scoring" as this fails the Validation and relative path to scoring file is expected
@jonringer