ImportError when scheduling python code to run using crontab - python

This code runs fine from shell without errors:
import urllib.request
When I schedule for it to run using crontab, it throws this error:
Traceback (most recent call last):
File "/home/pi/Documents/pyemail/ipemailer.py", line 2, in <module>
import urllib.request
ImportError: No module named request

The module urllib.request was only made available starting Python3.
From the old urllib docs from Python2.7:
The urllib module has been split into parts and renamed in Python 3 to urllib.request, urllib.parse, and urllib.error error.
The cron utility is a system tool, which most likely also uses the system Python, which is most likely Python 2.7. You'll have to explicitly tell cron that you want to use Python 3 instead.
You can do this by adding a shebang at the top of your Python script that specifies Python 3:
#!/usr/bin/python3
To get the correct shebang, do:
$ which python3
/usr/bin/python3
Then in your crontab list:
0 5 * * 1-5 /path/to/my-python-script.py
Make sure to make the script executable by doing
$ chmod +x /path/to/my-python-script.py
$ ls -l /path/to/my-python-script.py
-rwxr-xr-x 1 root root 3.5K 10月 1 08:52 /path/to/my-python-script.py
UPDATE:
If you want to check which Python interpreter is being used by your script, add this at the top:
import sys
print(sys.version)

Related

Can't import Python module even though it is in the PYTHONPATH

I'm trying to run Pixar's USDZ converter tool but i can't seem to run the Python script, it complains with the error Error: failed to import pxr module. Please add path to USD Python bindings to your PYTHONPATH.
I am doing this on Ubuntu instead of the native MacOS, but i have compiled from source the USD library, located in /usr/local/USD/.
Runnig the script outputs the above error:
$ ./usdzconvert -h
Error: failed to import pxr module. Please add path to USD Python bindings to your PYTHONPATH
even though I have added the path to the PYTHONPATH:
$ echo $PYTHONPATH
:/usr/local/USD/lib/python:/usr/local/USD/lib/python/pxr:/usr/local/USD/lib
furthermore Python seems to see that just fine:
$ python3 -c 'import sys; print(sys.path)'
['', '/home/julien', '/usr/local/USD/lib/python', '/usr/local/USD/lib/python/pxr', '/usr/local/USD/lib', '/usr/lib/python36.zip', '/usr/lib/python3.6', '/usr/lib/python3.6/lib-dynload', '/usr/local/lib/python3.6/dist-packages', '/usr/lib/python3/dist-packages']
I've also tried adding print(sys.path) to the begining of the script to confirm it was loading the same env variable and running it i get the same path as above.
The script portion that throws the error is as follows:
#!/usr/bin/env python3
import os.path
from os import chdir
import sys
import importlib
import tempfile
from shutil import rmtree
import zipfile
usdLibLoaded = True
kConvertErrorReturnValue = 2
if sys.version_info.major != 3:
print(' \033[93mWarning: It is recommended to use Python 3. Current version is ' + str(sys.version_info.major) + '.\033[0m')
try:
from pxr import *
import usdUtils
except ImportError:
print(' \033[91mError: failed to import pxr module. Please add path to USD Python bindings to your PYTHONPATH\033[0m')
usdLibLoaded = False
I don't know anything about python so I am at loss to figure out this import issue, any ideas?
I have python 2 and 3 installed:
$ python --version
Python 2.7.17
python3 --version
Python 3.6.9
but considering the script starts off with a shebang instructing to use python3 i would think this would be fine, no?
I don't known why, but sometimes, something like this worked for me:
PYTHONPATH=. ./usdzconvert -h
How about this:
#!/usr/bin/env python3
import os.path
from os import chdir
import sys
import importlib
import tempfile
from shutil import rmtree
import zipfile
usdLibLoaded = True
kConvertErrorReturnValue = 2
if sys.version_info.major != 3:
print(' \033[93mWarning: It is recommended to use Python 3. Current version is ' + str(sys.version_info.major) + '.\033[0m')
pxr_path = '/usr/local/USD/lib/python/pxr'
sys.path.append(pxr_path)
sys.path.append(os.path.dirpath(pxr_path))
try:
from pxr import *
import usdUtils
except ImportError:
print(' \033[91mError: failed to import pxr module. Please check the path to USD\033[0m')
usdLibLoaded = False
So I've finally figured out what the problem was.
I've modified the python script to print the actual import message and this is what I got:
dynamic module does not define module export function (PyInit__tf)
A quick google search brought me to this answer that explains that the module was compiled with python 2, so I recompiled USD with python 3 and re-installed all its corresponding v3 dependencies and then I ran the script again and this time no more import error.

crontab and ImportError: No module named psycopg2

Im trying to create a cron job that runs every 15 minutes
*/15 * * * * cd Desktop && /usr/bin/python myFile.py >> myLog 2>&1
When this tries to run, I get this error in myLog
Traceback (most recent call last):
File "myFile.py", line 1, in <module>
import psycopg2
ImportError: No module named psycopg2
Even though when I run it manually in visual studio code with command python myFile.py it runs with no errors and has no issues with psycopg2...any idea whats happening?
Your system might be using Python2 by default at /usr/bin/python. Check if that is the issue and change it to the path either your Python3 executable path or the path of your virtual environment's executable and run.
Also, a better approach would be to have a shell script be executed via crontab and that script internally either activates your virtual environment or runs the program directly after cd-ing into the directory

Getting crontab on MAC to run anaconda installed python script (module not found)

I am trying to set up crontab for a script written in python which is intalled via Anaconda. The simple .py runs (it just loads a module for a demo) and can be run in terminal with python a.py .
The problem is getting crontab the path for python and imported modules.
I have been trying to set the PATH and PYTHONPATh to the python directory and also where pandas is located. I think this is a env issue but have no idea what that means. Any ideas?
The crontab is:
SHELL=/bin/sh
PYTHONPATH=/Users/Esel/anaconda3/bin/python
* * * * * cd /Users/Esel/Documents/x/y/z && python a.py
The python (test) script:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Thu Jul 18 21:36:34 2019
#author: Esel
"""
import pandas
print('hello kitty')
# This is a test
Crontab mails the following statement:
Traceback (most recent call last):
File "a.py", line 3, in
import pandas
ImportError: No module named pandas
You're setting an env.var, cd'ing to a directory, and calling an interpreter, all from crontab.
Under those circumstances, personally I'd find it more elegant to just create a small wrapper script (here called pyscript) that does all that, and call that script from crontab:
$> cat /home/me/bin/pyscript
#!/bin/bash
# a.py needs module pandas in /foo/bar
export PYTHONPATH=/foo/bar
cd /Users/Esel/Documents/x/y/z || exit
python a.py
$> chmod ug+rx /home/me/bin/pyscript
$> cat /var/spool/cron/crontabs/me
...
* * * * * /home/me/bin/pyscript
With some ideas from a roadowl (thanx) and another SOverflow question (54564187) I think I got it running.
SHELL=/bin/sh
PATH=$PATH/Users/Esel/anaconda3/bin:/Users/Esel/anaconda3/condabin:/Applications/anaconda3/bin:/Applications/anaconda3/bin:/Users/Esel/anaconda3/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
* * * * * cd /Users/Esel/Documents/x/y/z && python a.py
The path came from
echo $PATH

Mac gcloud install ImportError: No module named __future__

When installing gcloud for mac I get this error when I run the install.sh command according to docs here:
Traceback (most recent call last):
File "/path_to_unzipped_file/google-cloud-sdk/bin/bootstrapping/install.py", line 8, in <module>
from __future__ import absolute_import
I poked through and echoed out some stuff in the install shell script. It is setting the environment variables correctly (pointing to my default python installation, pointing to the correct location of the gcloud SDK).
If I just enter the python interpreter (using the same default python that the install script points to when running install.py) I can import the module just fine:
>>> from __future__ import absolute_import
>>>
Only other information worth noting is my default python setup is a virtual environment that I create from python 2.7.15 installed through brew. The virtual environment python bin is first in my PATH so python and python2 and python2.7 all invoke the correct binary. I've had no other issues installing packages on this setup so far.
If I echo the final line of the install.sh script that calls the install.py script it shows /path_to_virtualenv/bin/python -S /path_to_unzipped_file/google-cloud-sdk/bin/bootstrapping/install.py which is the correct python. Or am I missing something?
The script uses the -S command-line switch, which disables loading the site module on start-up.
However, it is a custom dedicated site module installed in a virtualenv that makes a virtualenv work. As such, the -S switch and virtualenvs are incompatible, with -S set fundamental imports such as from __future__ break down entirely.
You can either remove the -S switch from the install.bat command or use a wrapper script to strip it from the command line as you call your real virtualenv Python.
I had the error below when trying to run gcloud commands.
File "/usr/local/Caskroom/google-cloud-sdk/latest/google-cloud-sdk/lib/gcloud.py", line 20, in <module>
from __future__ import absolute_import
ImportError: No module named __future__
If you have your virtualenv sourced automatically you can specify the environment variable CLOUDSDK_PYTHON i.e. set -x CLOUDSDK_PYTHON /usr/bin/python to not use the virtualenv python.
In google-cloud-sdk/install.sh go to last line, remove variable $CLOUDSDK_PYTHON_ARGS as below.
"$CLOUDSDK_PYTHON" $CLOUDSDK_PYTHON_ARGS "${CLOUDSDK_ROOT_DIR}/bin/bootstrapping/install.py" "$#"
"$CLOUDSDK_PYTHON" "${CLOUDSDK_ROOT_DIR}/bin/bootstrapping/install.py" "$#"

Scheduling cronjob using python cannot find module bs4

I wrote a script to scrape some web data that I would like to run every 10 minutes. The script runs fine when I do it from the command line but I get an error when I try to run it using a cronjob every 10 minutes because it can't import bs4'. I get this error:
No module named bs4
My crontab:
*/10 * * * * PYTHONPATH=/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages python /Users/{username}/Documents/scripts/cot.py
I got the PYTHONPATH variable by finding where 'bs4' was downloaded using this command:
python -c 'import bs4; print(bs4.__file__)'
Output in /var/{username}/mail:
X-Cron-Env: <SHELL=/bin/sh>
X-Cron-Env: <PATH=/usr/bin:/bin>
X-Cron-Env: <LOGNAME={username}>
X-Cron-Env: <USER={username}>
X-Cron-Env: <HOME=/Users/{username}>
Message-Id: <20171223194001.0783F8639E1#mbp-0500.localdomain>
Date: Sat, 23 Dec 2017 13:40:00 -0600 (CST)
Traceback (most recent call last):
File "/Users/{username}/Documents/scripts/cot.py", line 3, in <module>
from bs4 import BeautifulSoup
ImportError: No module named bs4
Had the same problem. In my case the job was executed by root and not in user mode. Be sure to execute the cronjob in user mode. The right solution was answered here
I was having the same issue with bs4 and python.
I eventually solved it by creating a shell script (making it executable with chmod +x) then executing that script from the command line (./scraper.sh)
bs4 was installed but it threw an error so I downloaded it again with pip using the --user flag (pip3 install bs4 --user), and it worked fine.
Then I set the crontab to run the shell script (I think running it as a shell script preserves some of the environmental variables that python or conda needs, read that in a different question)
Hope this helps!

Categories