ModuleNotFoundError

Cron Job ModuleNotFoundError: Fix Python Import Paths

Your Python script works manually but fails in cron with ModuleNotFoundError. It's almost always a PATH or sys.path mismatch — cron runs with a stripped environment.

Quick answer

Cron runs with a minimal environment, so Python can't find your modules. Fix it by setting the full path to your Python interpreter, activating your virtualenv inside the cron command, and exporting the right PYTHONPATH — or just wrap the whole thing in a shell script that sources your environment first.

Why this happens

You've tested your script a dozen times in the terminal. You type python3 my_script.py, it runs, everyone's happy. Then you drop it in crontab, wait five minutes, and get an email saying ModuleNotFoundError: No module named 'requests'. Frustrating, right?

Here's the deal. Cron doesn't load your shell profile. It doesn't source .bashrc, it doesn't know about your virtualenv, and it sure as hell doesn't know where pip put your packages. When you run a command in your terminal, you inherit your user's environment — PATH, VIRTUAL_ENV, everything. Cron gets a bare-bones environment with PATH=/usr/bin:/bin and nothing else. So when cron fires up python3, it's using the system Python, not the one from your venv where you installed requests.

I had a client last month whose nightly backup script died for three weeks straight because of this. They'd installed everything under a pyenv virtualenv, and cron kept picking up /usr/bin/python3. Nobody noticed until the disk filled up.

Step-by-step fix

1. Find the full path to your Python interpreter

Inside the environment where your script works, run:

which python3
# e.g. /home/youruser/venv/bin/python3

Copy that path. You'll need it in a second.

2. Update your crontab to use the explicit interpreter

Open your crontab with crontab -e and change the command from this:

*/5 * * * * python3 /home/youruser/scripts/my_script.py

To this:

*/5 * * * * /home/youruser/venv/bin/python3 /home/youruser/scripts/my_script.py

That alone fixes 70% of these cases. The interpreter now knows where its own site-packages live.

3. Set PYTHONPATH if your modules live outside site-packages

If you're importing your own .py files from a sibling directory, you need to tell Python where to look. Add this line at the top of your crontab:

PYTHONPATH=/home/youruser/myproject
*/5 * * * * /home/youruser/venv/bin/python3 /home/youruser/scripts/my_script.py

Multiple paths? Separate them with colons, just like PATH.

4. Set PATH and HOME too — cron is dumb

Some modules shell out to other binaries, and without a sane PATH they'll fail too. Throw this at the top of the crontab:

PATH=/home/youruser/venv/bin:/usr/local/bin:/usr/bin:/bin
HOME=/home/youruser
PYTHONPATH=/home/youruser/myproject

Yes, you can set env vars in crontab. They apply to every job below them.

5. Test with the exact cron environment

Don't guess. Reproduce cron's stripped environment manually:

env -i /home/youruser/venv/bin/python3 /home/youruser/scripts/my_script.py

env -i clears everything. If this works, cron will work. If it doesn't, you now see the real error without waiting five minutes.

Alternative fixes if that doesn't cut it

Wrap it in a shell script

This is my go-to for anything non-trivial. Create /home/youruser/scripts/run_backup.sh:

#!/bin/bash
source /home/youruser/venv/bin/activate
export PYTHONPATH=/home/youruser/myproject
cd /home/youruser/myproject
python my_script.py

chmod +x it, then point cron at the script. Now your environment setup lives in a file you can actually read and debug instead of a cramped crontab line.

Use the shebang line

If your script starts with #!/home/youruser/venv/bin/python3, you can call it directly from cron. Just make sure the file is executable. This is clean but brittle if you ever move the venv.

Switch to systemd timers

Honestly? On modern Linux, systemd timers are a better fit for anything important. They let you specify Environment=, WorkingDirectory=, and User= cleanly, and you get proper logging with journalctl. Cron is fine for quick stuff, but I've moved three clients off it this year for critical jobs.

Prevention tip

Never rely on cron inheriting your shell environment — it never will. Every cron job that runs Python should have an explicit interpreter path and a PYTHONPATH set at the top of the crontab (or in a wrapper script). And before you deploy, run env -i against the exact command. If it passes that test, you won't get a 3 AM email about a missing module.

Related Errors in Programming & Dev Tools
0XC00002C9 0xC00002C9: NaT Consumption Fault on Itanium – Quick Fix error: failed to push some refs to Git non-fast-forward push error: 3 fixes that actually work 0X000002B7 Fix ERROR_DBG_RIPEXCEPTION (0X000002B7) in Visual Studio Debugger 0X80000007 STATUS_WAKE_SYSTEM_DEBUGGER: Wake Reason and Fix

Was this solution helpful?

EP
Erropedia Team
Tech Support Editors
The Erropedia editorial team researches and documents real-world tech errors from across Windows, Linux, macOS, networking, databases, cloud platforms, and more. Every solution is reviewed for accuracy and updated as software and systems evolve.