Calling a .py script from a specific file path in Python interpreter - python

I am just getting started with Python.
How do I call a test script from C:\X\Y\Z directory when in Python interpreter command line in interactive mode? How do I specify the full path for the file when it is not in the current working directory?
I can call a test script when using the windows run command with "python -i c:\X\Y\Z\filename.py" and it runs fine. But I want to be able to call it form the Python terminal with the ">>>" prompt.
(I searched and searched for two hours and could not find an answer to this, although it seems like it should be a common question for a beginner and an easy thing to do.)
Thanks

Since you are using backslashes for the file path, python interprets those as "escape characters." When writing the file path in Python, make sure to use forward slashes.
with open("C:/X/Y/Z/filename.py", "r") as file:
exec(file.read())
Double backslashes also work, but I prefer the cleaner look of forward slashes.

If you want to import it into the REPL:
import sys
sys.path.append('c:\X\Y\Z')
import filename

If you want to execute code from a file within the interpreter, you can use execfile
execfile('C:/X/Y/Z/filename.py')
(/ works as path separator in all operating systems, if you use \, you need to escape them ('C:\\X\\Y\\Z\\filename.py')or use raw string literal (r'C:\X\Y\Z\filename.py'))

If you are using IPython (and you should use, it's much more useful than vanilla interactive Python), you can use magic function run (or with % prefix: %run):
run C:\\X\\Y\\Z\\filename.py
%run C:\\X\\Y\\Z\\filename.py
See this link for more information about magic functions.
And by the way, it has even auto completion of filenames.

Exec the heck out of it
Python 2.x:
execfile("C:\\X\Y\\Z")
Python 3+:
with open("C:\\X\Y\\Z", "r") as f:
exec(f.read())
Still, that is very bad practice - it executes code from a string (at some point), instead of using preferred and safer way of importing modules. Still, when you import module and have some of its code after "-f __name__ == '__main__':", that parts won't work (because __name__ in imported module won't be __main__, and it would be, if you ran it as single script).
It is bad for many reasons, in some sense strongly connected to Zen of Python, but if you're beginner, this should speak to you:
When you do anything in interactive mode, you work on some namespace (this term is very important for understanding python, if you don't know it, check it in python language reference). When you exec()/execfile() something without providing globals()/locals(), you may end up with modified namespace.
Modified namespace?
What does it mean? Lets have a script like that:
radius = 3
def field_of_circle(r):
return r*r*3.14
print(field_of_circle(radius))
Now, you have following session:
>>>radius = 5
>>>execfile("script_above.py")
28.26
>>>print(radius)
3
You see what happens? Variables defined by you in interactive session will get overwritten by values from end of script. The same goes for modifying already imported external modules. Lets have a very simple module:
x = 1
and executed script:
import very_simple_module
very_simple_module.x = 3
Now, here's a interpreter interactive session:
>>>import very_simple_module
>>>print(very_simple_module.x)
1
>>>execfile("executed_script.py")
>>>print(very_simple_module.x)
3
Run another interpreter
Interactive sessions are very useful for many things, but not for many things, but running python scripts is not one of them.
Unless... you wanna play tough and use python shell as system shell. Then, you can use subprocess (in standard library) or sh (which can be found on PyPI):
>>>import subprocess
>>>subprocess.call(["python", "C:\\X\Y\\Z"], shell=True)
>>>from sh import python
>>>python("C:\\X\Y\\Z")
Those won't have this problem with modifying interactive interpreters namespace
See script as module
Also, there is one more option: in interactive session add directory with script to pythonpath, and import module named as script:
>>>import sys
>>>if "C:\\X\\Y" not in sys.path:
sys.path.append("C:\\X\\Y")
>>>import Z
Remember that directory in which interpreter was started is automatically on pythonpath, so if you've ran python in the same directory as your script, you just have to use 3rd of lines above.
Interpreters namespace won't change, but code after "-f __name__ == '__main__':" won't be executed. Still you can access scripts variables:
>>>radius = 5
>>>import first_example_script
>>>print(radius)
5
>>>print(first_example_script.radius)
3
Also, you can have module name conflict. For example, if your script was sys.py, then this solution will work, because python will import builtin sys module before yours.

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

Python pdb on python script run as package

I have a python program that I usually run as a part of a package:
python -m mymod.client
in order to deal with relative imports inside "mymod/client.py." How do I run this with pdb - the python debugger. The following does not work:
python -m pdb mymod.client
It yields the error:
Error: mymod.client does not exist
EDIT #1 (to address possible duplicity of question)
My question isn't really about running two modules simultaneously python, rather it is about how to use pdb on a python script that has relative imports inside it and which one usually deals with by running the script with "python -m."
Restated, my question could then be, how do I use pdb on such a script while not having to change the script itself just to have it run with pdb (ie: preserving the relative imports inside the script as much as possible). Shouldn't this be possible, or am I forced to refactor in some way if I want to use pdb? If so what would be the minimal changes to the structure of the script that I'd have to introduce to allow me to leverage pdb.
In summary, I don't care how I run the script, just so long as I can get it working with pdb without changing it's internal structure (relative imports, etc) too much.
I think I have a solution.
Run it like this:
python -m pdb path/mymod/client.py arg1 arg2
that will run it as a script, but will not treat it as a package.
At the top of client.py, the first line should be:
import mymod
That will get the package itself loaded.
I am still playing with this, but it seems to work so far.
This is not possible. Though unstated in documentation, Python will not parse two modules via the -m command line option.

Running python script inside ipython

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')

Python meta-debugging

Heyo,
Just started writing an assembler for the imaginary computer my class is creating wire-by-wire since the one the TA's provided sucks hard. I chose python even though I've never really used it that much (but know the basic syntax) and am loving it.
My favorite ability is how I can take a method I just wrote, paste it into the shell and then unit test it by hand (I'm using IDLE).
I'm just wondering if there is a way to expose all the symbols in my python code to the shell automatically, so I can debug without copying and pasting my code into the shell every time (especially when I make a modification in the code).
Cheers
you can import the module that your code is in. This will expose all of the symbols prefixed with the module name.
The details for the easiest way to do it depend on your operating system but you can always do:
>>> sys.path.append('/path/to/directory/that/my/module/is/in/')
>>> import mymod #.py
later after you make a change, you can just do
>>>> reload(mymod)
and the symbols will now reference the new values. Note that from mymod import foo will break reload in the sense that foo will not be updated after a call to reload. So just use mymod.foo.
Essentially the trick is to get the directory containing the file on your PYTHONPATH environment variable. You can do this from .bashrc on linux for example. I don't know how to go about doing it on another operating system. I use virualenv with has a nice wrapper and workon command so I just have to type workon foo and it runs shell scripts (that I had to write) that add the necessary directories to my python path.
When I was just starting off though, I made one permanent addition to my PYTHONPATH env variable and kept module I wrote in there.
Another alternative is to execute your module with the -i option.
$ python -i mymod.py
This will execute the module through to completion and then leave you at the interpreter. this isn't IDLE though, it's a little rougher but you are now in your module's namespace (or rather the module's namespace is the global namespace)
Check IPython. It's enhanced interactive Python shell. You can %run your script and it will automatically expose all your global objects to the shell. It's very easy to use and powerful. You can even debug your code using it.
For example, if your script is:
import numpy as np
def f(x):
return x + 1
You can do the following:
%run yourScript.py
x = np.eye(4)
y = f(x)

Categories