Running python script inside ipython - python

Is it possible to run a python script (not module) from inside ipython without indicating its path? I tried to set PYTHONPATH but it seems to work only for modules.
I would like to execute
%run my_script.py
without being in the directory containing the file.

from within the directory of "my_script.py" you can simply do:
%run ./my_script.py

How to run a script in Ipython
import os
filepath='C:\\Users\\User\\FolderWithPythonScript'
os.chdir(filepath)
%run pyFileInThatFilePath.py
That should do it

The %run magic has a parameter file_finder that it uses to get the full path to the file to execute (see here); as you note, it just looks in the current directory, appending ".py" if necessary.
There doesn't seem to be a way to specify which file finder to use from the %run magic, but there's nothing to stop you from defining your own magic command that calls into %run with an appropriate file finder.
As a very nasty hack, you could override the default file_finder with your own:
IPython.core.magics.execution.ExecutionMagics.run.im_func.func_defaults[2] = my_file_finder
To be honest, at the rate the IPython API is changing that's as likely to continue to work as defining your own magic is.

In python there is no difference between modules and scripts; You can execute both scripts and modules. The file must be on the pythonpath AFAIK because python must be able to find the file in question. If python is executed from a directory, then the directory is automatically added to the pythonpath.
Refer to What is the best way to call a Python script from another Python script? for more information about modules vs scripts
There is also a builtin function execfile(filename) that will do what you want

Not exactly the answer to your question, but you can drop into ipython at the end of a script's execution by using the -i parameter to ipython:
ipython -i my_script.py
At the end of the script you're dropped into the ipython prompt with the script's variables available to you, just like python -i.

for Python 3.6.5
import os
os.getcwd()
runfile('testing.py')

Related

How would I allow others to use my script from anywhere in the shell without having to type out the file extension?

Excuse the awkward question wording.
I've made a script. I would like for others to download it from github, and run it by typing programName argument1 argument2, similar to any other popular app used through the terminal such as Jupyter or even opening Atom/Sublime/etc. (ex:jupyter notebook, atom .). However, unlike Jupyter or sublime, my script isn't launching another app, it's a small app meant to be used in the shell.
Currently, to use my script, one must type into the command line python programName.py arg1 etc from within the file's directory.
How do I allow others to dl it and use it from anywhere (not having to be within the directory), without having to type out the whole python programName.py part, and only having to type programName arg1?
This blog post explains step by step how to create a distribution that you can install and it would turn into an executable.
You can refer to this github repo for a sample application.
The full documentation of setuptools is available here.
In general, you should configure your setup.py in order to use the command in the entry-point option:
setup(
name = "your_app_name",
packages = ["package_name"],
entry_points = {
"console_scripts": ['cmd_name = package_name.package_name:main']
},
....
)
This solution would work on every OS where you have installed python.
Your script may need to have an interpreter, "shebang", besides being "reachable" by the $PATH
#!interpreter [optional-arg]
For example, you could have something like
#!/usr/bin/env python
or to force a specific version
#!/usr/local/bin/python2.7
Next, your script needs to be available within the $PATH, check this answer that covers that part: https://unix.stackexchange.com/q/29608/53084
You can simply add your script to PATH variable in order to launch it from anywhere.
In Linux distros, you can simply do it by using a bash command PATH=$PATH:/path/to/your/script.
Make sure you don't have the space around the "=" operator.
Now, the second thing is you don't want your script to be named as pythonProgram.py.You can simply remove the extension .py from PythonProgram.py by adding a single line to the starting of your script.
Open up your script and at the very begining type #!/usr/bin/python.This should be the first line of your code.This line is called shebang and is used to tell the bash which interpreter to be used for compiling the script.
If everything went right, you will be able to run your script as pythonProgram arg1.
In addition to mabe02: Python is a scripting language and usually not compiled, which means you will need an interpreter to run your program.
Programms made in C f.e. can be run on its own because they were compiled into machine code by a compiler.
An interpreter is similar to a compiler as it reads your script and interprets it at runntime. That is why you need to write python before your programm, to tell your computer to interpret your script on runntime, using python. This doesn't mean that there are no possibilities to compile python as can be seen in the other answer and in this link Can a python program be run on a computer without Python? What about C/C++? (py2exe and py2app).

Using a compiled Python shell in Linux

Is it possible to use a "more complex" shell than just a single command shell? We have written a python shell that is a command loop, and it works fine in /etc/passwd like this:
user:x:1000:1000::/home/user:/usr/bin/ourshell.py
Of course the Python file has the shebang line for /usr/bin/python in it. However, we'd like to compile the Python shell into a .pyc file to save a bit of time on execution in login. So, after compiling, I've been trying to "quote" the shell line in /etc/passwd as "python ourshell.pyc", and I even tried making the shell a bash script which simply executes that same command (with the initial arguments).
Of course none of this has worked. When we SSH in, there is always some kind of error. Is there any special trick to what I am trying to do?
CPython's .pyc files are not text, and do not allow use of a shebang line. The traditional method is to have your called script be tiny; it would simply import a module with the rest of the program, which can then be precompiled. For instance, here is the main script of xonsh:
#!/usr/bin/env python3 -u
from xonsh.main import main
main()
This script takes negligible time to compile. It is also possible to run installed modules using -m, but that takes module names, not filenames, so is not suitable for a shebang script.
I suggest to code a small C wrapper program running your python shell.
(notice that execve(2) forbids nested shebang interpreters; I don't know if that applies for your case)
Look into your log files, probably /var/log/messages and /var/log/auth.log
You may also need to explicitly add (the compiled C executable for the wrapper) to /etc/shells; see shells(5)
Look also into scsh.
Your sshd daemon is probably using Linux Plugin Authentification Modules. So read more about PAM.
Create a file /usr/bin/shell_wrapper that contains this one line:
#!/usr/bin/python /usr/bin/ourshell.pyc
The compiled bytecode ourshell.pyc has to live in /usr/bin, or else change the path accordingly. The python path should go to the same version that compiled the bytecode.
Then make sure to have your /etc/passwd use /usr/bin/shell_wrapper for the shell executable:
user:x:1000:1000::/home/user:/usr/bin/shell_wrapper

How do i know if a script is to be run with Python 2 or Python 3 [duplicate]

How do I, in the main.py module (presumably), tell Python which interpreter to use? What I mean is: if I want a particular script to use version 3 of Python to interpret the entire program, how do I do that?
Bonus: How would this affect a virtualenv? Am I right in thinking that if I create a virtualenv for my program and then tell it to use a different version of Python, then I may encounter some conflicts?
You can add a shebang line the to the top of the script:
#!/usr/bin/env python2.7
But that will only work when executing as ./my_program.py.
If you execute as python my_program.py, then the whatever Python version that which python returns will be used.
In re: to virtualenv use: virtualenv -p /usr/bin/python3.2 or whatever to set it up to use that Python executable.
Perhaps not exactly what you asked, but I find this to be useful to put at the start of my programs:
import sys
if sys.version_info[0] < 3:
raise Exception("Python 3 or a more recent version is required.")
I would use the shebang #!/usr/bin/python (first line of code) with the serial number of Python at the end
Then run the Python file as a script, e.g., ./main.py from the command line, rather than python main.py.
It is the same when you want to run Python from a Linux command line.
While the OP may be working on a nix platform this answer could help non-nix platforms. I have not experienced the shebang approach work in Microsoft Windows.
Rephrased: The shebang line answers your question of "within my script" but I believe only for Unix-like platforms. Even though it is the Unix shell, outside the script, that actually interprets the shebang line to determine which version of Python interpreter to call. I am not sure, but I believe that solution does not solve the problem for Microsoft Windows platform users.
In the Microsoft Windows world, the simplify the way to run a specific Python version, without environment variables setup specifically for each specific version of Python installed, is just by prefixing the python.exe with the path you want to run it from, such as C:\Python25\python.exe mymodule.py or D:\Python27\python.exe mymodule.py
However you would need to consider the PYTHONPATH and other PYTHON... environment variables that would point to the wrong version of Python libraries.
For example, you might run:
C:\Python2.5.2\python.exe mymodule
Yet, the environment variables may point to the wrong version as such:
PYTHONPATH = D:\Python27
PYTHONLIB = D:\Python27\lib
Loads of horrible fun!
So a non-virtualenv way, in Windows, would be to use a batch file that sets up the environment and calls a specific Python executable via prefixing the python.exe with the path it resides in. This way has additional details you'll have to manage though; such as using command line arguments for either of the "start" or "cmd.exe" command to "save and replace the "console" environment" if you want the console to stick around after the application exits.
Your question leads me to believe you have several Python modules, each expecting a certain version of Python. This might be solvable "within" the script by having a launching module which uses the subprocess module. Instead of calling mymodule.py you would call a module that calls your module; perhaps launch_mymodule.py
launch_mymodule.py
import sys
import subprocess
if sys.argv[2] == '272':
env272 = {
'PYTHONPATH': 'blabla',
'PYTHONLIB': 'blabla', }
launch272 = subprocess.Popen('D:\\Python272\\python.exe mymodule.py', env=env272)
if sys.argv[1] == '252'
env252 = {
'PYTHONPATH': 'blabla',
'PYTHONLIB': 'blabla', }
launch252 = subprocess.Popen('C:\\Python252\\python.exe mymodule.py', env=env252)
I have not tested this.
You can't do this within the Python program, because the shell decides which version to use if you a shebang line.
If you aren't using a shell with a shebang line and just type python myprogram.py it uses the default version unless you decide specifically which Python version when you type pythonXXX myprogram.py which version to use.
Once your Python program is running you have already decided which Python executable to use to get the program running.
virtualenv is for segregating python versions and environments, it specifically exists to eliminate conflicts.
For those using pyenv to control their virtual environments, I have found this to work in a script:
#!/home/<user>/.pyenv/versions/<virt_name>/bin/python
DO_STUFF
I had this problem and just decided to rename one of the programs from python.exe to python2.7.exe. Now I can specify on command prompt which program to run easily without introducing any scripts or changing environmental paths.
So i have two programs: python2.7 and python (the latter which is v.3.8 aka default).
While working with different versions of Python on Windows,
I am using this method to switch between versions.
I think it is better than messing with shebangs and virtualenvs
install python versions you desire
go to Environment Variables > PATH
(I assume that paths of python versions are already added to Env.Vars.>PATH)
suppress the paths of all python versions you dont want to use
(don't delete the paths, just add a suffix like "_sup")
call python from terminal
(so Windows will skip the wrong paths you changed,
and will find the python.exe at the path you did not suppressed,
and will use this version after on)
switch between versions by playing with suffixes

How to know if I run python from Textmate/emacs?

I use TextMate to debug python script, as I like the feature of using 'Command-R' for running python from TextMate, and I learned that emacs provide similar feature.
I need to know if the python is run from command line or from TextMate/emacs. How can I do that?
ADDED
I use TextMate for python coding/debugging, and it's pretty useful. But, sometimes I need to run the test using command line. I normally turn on debugging/logging mode with TextMate, and off with command line mode. This is the reason I asked the question. Also, I plan to use emacs for python debugging, so I wanted to ask the case for emacs.
I got an answer in the case with emacs, and I happen to solve this issue with TextMate.
Set variables in Preferences -> Advanced -> Shell Variables, and I found that TM_ORGANIZATION_NAME is already there to be used. So, I'll just use this variable.
Use this variable, if os.environ['TM_ORGANIZATION_NAME']: return True
I guess the shell variable from TextMate disappear when I'm done using it.
For Emacs: If python is run as an inferior process, then the environment variable INSIDE_EMACS will be set.
From docs:
Emacs sets the environment variable
INSIDE_EMACS in the subshell to a
comma-separated list including the
Emacs version. Programs can check this
variable to determine whether they are
running inside an Emacs subshell.
sys.argv will tell you how Python was invoked. I don't know about TextMate, but when I tell Emacs to eval buffer, its value is ['-c']. That means it's executing a specified command, according to the man page. If Python's run directly from the command line with no parameters, sys.argv will be []. If you run a python script, it will have the script name and whatever arguments you pass it. You might want to set up your python-mode in Emacs and whatever the equivalent in TextMate is to put something special like -t in the command line.
That's pretty hackish though. Maybe there's a better way.
From the docs for sys.path:
As initialized upon program startup,
the first item of this list, path[0],
is the directory containing the script
that was used to invoke the Python
interpreter. If the script directory
is not available (e.g. if the
interpreter is invoked interactively
or if the script is read from standard
input), path[0] is the empty string,
which directs Python to search modules
in the current directory first. Notice
that the script directory is inserted
before the entries inserted as a
result of PYTHONPATH.
So
if sys.path[0]:
# python was run interactively
else:
# python is running a script.
Or, for example, from the IPython prompt (inside Emacs):
In [65]: sys.path
Out[65]:
['', <-------------------- first entry is empty string
'/usr/bin',
'/usr/local/lib/python2.6/dist-packages/scikits.statsmodels-0.2.0-py2.6.egg',
'/usr/local/lib/python2.6/dist-packages/pyinterval-1.0b21-py2.6-linux-i686.egg',
... ]
Use Command-R to run the script directly
Use Shift-Command-R to run the script from terminal.

How do I execute (not import) a python script from a python prompt?

I need to execute a Python script from an already started Python session, as if it were launched from the command line. I'm thinking of similar to doing source in bash or sh.
In Python 2, the builtin function execfile does this.
execfile(filename)
If you're running ipython (which I highly recommend for interactive python sessions), you can type:
%run filename
or
%run filename.py
to execute the module (rather than importing it). You'll get file-name completion, which is great for ReallyLongModuleName.py (not that you'd name your modules like that or anything).

Categories