How to import packages in virtualenv in python shell - python

I'm trying to make a function to make periodical notifications to users , especially , ios mobile devices.
Specifically, I use 'Scheduled task' of pythonanywhere. (https://help.pythonanywhere.com/pages/ScheduledTasks)
This is my script to send notifications.
#!/usr/local/bin/python3.4
import sys,os,django
sys.path.append("/home/lkm/Folder/project/")
sys.path.append("/home/lkm/Folder/project/app/myvenv/")
print(sys.path)
os.environ["DJANGO_SETTINGS_MODULE"] = "project.settings"
from push_notifications.models import APNSDevice, GCMDevice
device = APNSDevice.objects.all()
if device is None:
print('No Device')
message = 'Home Fried Potatoes, Yo-nola Bar, Soup du Jour, More...'
device.send_message(message)
But at the line of 'from push_notifications.models import APNSDevice, GCMDevice'
I'm getting an error :
'ImportError: No module named 'push_notifications'
I think it's because of not importing virtualenv because push_notifications package is inside of packages of virtualenv, in mycase 'myvenv' directory.
But even though I import 'myvenv' by 'ImportError: No module named 'push_notifications'.
It makes the same error, do you have the solution for this?
UPDATE (First script , second error message)
#!/home/lkm/folder/project/app/myvenv/bin/python
import sys,os,django
sys.path.append("/home/lkm/folder/project/application/myvenv/bin/../lib/python/site-packages")
print(sys.path)
os.environ["DJANGO_SETTINGS_MODULE"] = "project.settings"
from push_notifications.models import APNSDevice, GCMDevice
device = APNSDevice.objects.all()
if device is None:
print('No Device')
message = 'Home Fried Potatoes, Yo-nola Bar, Soup du Jour, More...'
device.send_message(message)
['/home/lkm/folder/project/application', '/usr/lib/python3.4',
'/usr/lib/python3.4/plat-x86_64-linux-gnu',
'/usr/lib/python3.4/lib-dynload',
'/usr/local/lib/python3.4/dist-packages',
'/usr/lib/python3/dist-packages',
'/home/lkm/folder/project/application/myvenv/bin/../lib/python/site-packages']
Traceback (most recent call last): File
"/home/lkm/folder/project/application/schedule.py", line 9, in
from push_notifications.models import APNSDevice, GCMDevice ImportError: No module named 'push_notifications'

I would change the shebang to use the Python from your virtual environment.
#!/home/lkm/Folder/project/app/myvenv/bin/python
Then you shouldn't have to append the virtual env to the python path, and you can remove the following line.
sys.path.append("/home/lkm/Folder/project/app/myvenv/")
However, if you really want to manually add the virtual env directory to the Python path, then I think you want to include the site-packages directory instead:
sys.path.append("/home/lkm/Folder/project/app/myvenv/python3.4/site-packages")

How are you executing the file?
I see you have:
#!/usr/local/bin/python3.4
which means that if you're executing the file with:
./file.py
it will be executed with the system interpreter.
You need to activate the environment:
$ source env/bin/activate
and execute the file with:
$ python file.py
FWIW, I think the cleanest solution though is to have a setup.py script for your project (packages= argument being the most important) and define an entry point, similar to:
entry_points = {
'console_scripts': ['my-script=my_package.my_module:main'],
}
Then you run python setup.py develop after activating the environment
and you would run the script simply as a command:
$ my-script

Related

How to run Python script in venv?

Im trying to start telegram bot in Linux using venv. But bot starts only if venv activated manualy.
Python code:
#!env/bin/python3
# -*- coding: utf-8 -*-
import config
import telebot
bot = telebot.TeleBot(config.token)
#bot.message_handler(content_types=["text"])
def repeat_all_messages(message):
bot.send_message(message.chat.id, message.text)
if __name__ == '__main__':
bot.infinity_polling()
Bot starts with comands:
root#ubuntu-s-1vcpu-1gb-ams3-01:~/jira_bot# source env/bin/activate
(env) root#ubuntu-s-1vcpu-1gb-ams3-01:~/jira_bot# python3 sreda_bot.py
But if i try to start it without activating venv:
root#ubuntu-s-1vcpu-1gb-ams3-01:~/jira_bot# python3 sreda_bot.py
Traceback (most recent call last):
File "sreda_bot.py", line 4, in <module>
import telebot
ModuleNotFoundError: No module named 'telebot'
Finally I inserted full path to the interpreter in the venv in shebang line:
#!/root/jira_bot/env/bin/python3
Used ./sreda_bot.py instead of python3 sreda_bot.py. And it works fine.
Considering Python Shebang Syntax is like the following
#!interpreter [optional-arg]
You just need to locate your Virtual ENV's interpreter location.
#!<venv path>/bin/python[3.x]
Thus assuming your Virtual ENV is located at ~/jira_bot base from the following.
root#ubuntu-s-1vcpu-1gb-ams3-01:~/jira_bot# source env/bin/activate
(env) root#ubuntu-s-1vcpu-1gb-ams3-01:~/jira_bot# python3 sreda_bot.py
So your shebang should be #!/root/jira_bot/bin/python3
The purpose of virtual environments in Python is to create a physical separation between projects and their modules. In this case, the telebot module that you installed in the virtual environment, isn't in scope (available for use) outside of the virtual environment.

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" "$#"

Why is $PATH in remote deployment path different from $PATH in remote system?

I'm currently working on Pycharm with remote python Interpreter(miniconda3/bin/python).
So when I type echo $PATH in remote server, it prints
/home/woosung/bin:/home/woosung/.local/bin:/home/woosung/miniconda3/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
I created project in Pycharm and set remote python Interpreter as miniconda3 python, it works well when I just run some *.py files.
But when I typed some os.system() lines, weird things happened.
For instance, in test.py from Pycharm project
import os
os.system('echo $PATH')
os.system('python --version')
Output is
ssh://woosung#xxx.xxx.xxx.xxx:xx/home/woosung/miniconda3/bin/python -u /tmp/pycharm_project_203/test.py
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games
Python 2.7.12
Process finished with exit code 0
I tried same command in remote server,
woosung#test-pc:~$ echo $PATH
/home/woosung/bin:/home/woosung/.local/bin:/home/woosung/miniconda3/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
woosung#test-pc:~$ python --version
Python 3.6.6 :: Anaconda, Inc.
PATH and the version of python are totally different! How can I fix this?
I've already tried add os.system('export PATH="$PATH:$HOME/miniconda3/bin"') to test.py. But it still gives same $PATH.(/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games)
EDIT
Thanks to the comment of #Dietrich Epp, I successfully add interpreter path to the shell $PATH.
(os.environ["PATH"] += ":/home/woosung/miniconda3/bin")
But I stuck the more basic problem. When I add the path and execute command the some *.py file including import library which is only in miniconda3, the shell gives ImportError.
For instance, in test.py
import matplotlib
os.environ["PATH"] += ":/home/woosung/miniconda3/bin"
os.system("python import_test.py")
and import_test.py
import matplotlib
And when I run test.py,
Traceback (most recent call last):
File "import_test.py", line 1, in <module>
import matplotlib
ImportError: No module named matplotlib
Looks like the shell doesn't understand how to utilize modified $PATH.
I find the solution.
It is not direct but quite simple.
I changed os.system("python import_test.py") to os.system(sys.executable + ' import_test.py').
This makes the shell uses the Pycharm remote interpreter(miniconda3), not original.

Import python package after installing it with setup.py, without restarting?

I have a package that I would like to automatically install and use from within my own Python script.
Right now I have this:
>>> # ... code for downloading and un-targzing
>>> from subprocess import call
>>> call(['python', 'setup.py', 'install'])
>>> from <package> import <name>
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: No module named <package>
Then I can continue like this:
>>> exit()
$ python
>>> from <package> import <name>
And it works just fine. For some reason, Python is able to pick up the package just fine if I restart after running the setup.py file, but not if I don't. How can I make it work without having the restart step in the middle?
(Also, is there a superior alternative to using subprocess.call() to run setup.py within a python script? Seems silly to spawn a whole new Python interpreter from within one, but I don't know how else to pass that install argument.)
Depending on your Python version, you want to look into imp or importlib.
e.g. for Python 3, you can do:
from importlib.machinery import SourceFileLoader
directory_name = # os.path to module
# where __init__.py is the module entry point
s = SourceFileloader(directory_name, __init__.py).load_module()
or, if you're feeling brave that your Python path knows about the directory:
map(__import__, 'new_package_name')
Hope this helps,
I downloaded from seaborn from GitHub.
Through command prompt, cd to downloads\seaborn folder
python install setup.py
Then using spyder from anaconda, checked if it was installed by running the following in a console
import pip
sorted(["%s==%s" % (i.key, i.version)
for i in pip.get_installed_distributions()])
Seeing that it was not there, go to tools and select "Update module names list"
Again trying the previous code in a python console, the lib was still not showing.
Restarting Spyder and trying import seaborn worked.
Hope this helps.

ImportError when using web.py with new environment

I just recreated all my python environment, reinstalled python and setuptools, and installed virtualenv.
I started a test enviroment with virtualenv --no-site-packages test, activated it with Scripts\activate.bat and then easy_install web.py.
Then I create a code.py file:
import web
urls = (
'/.*', 'index',
)
app = web.application(urls, globals())
class index:
def GET(self):
return 'ok'
if __name__ == "__main__": app.run()
And I get the following error:
File "...\code.py", line 1, in <module>
import web
ImportError: No module named web
But if I use the interactive shell it works:
>>> import web
>>>
Everything done in the same cmd with the enviroment activated.
Does anyone know what is going on?
Edit:
It happens for every package installed within the environment. First it was web.py, now BeautifulSoup (same issue, cant find module, but import works in python shell)
Edit2:
The activate script is not setting the new python executable and the pythonpath print sys.executable gives C:\Python27\python.exe.
Solved.
Windows was configured to open .py files with C:\Python27\python.exe. I can even remember setting this mannualy some time ago so I wouldn't have to use python to run files (oh lazyness, what have you done to me?).
That's why it was working with the interactive shell, but not by executing the code.py file.
Running the file using python code.py works perfectly.

Categories