How to use pathlib along with subprocess - python

I would like to use relative paths along with subprocess module in order to be able to run different executables.
For getting relative paths and, after reading different threads, I think pathlib module is the best option to do that.
Let assume I have the python script in a particular folder in Windows. Inside it (the previous folder), I have other folders with the executables I want to run. Here it is when subprocess module comes in. However, I do not know how to include the relative paths created with pathlib module into subprocess args field.
From subprocess API I can read that 'args should be a sequence of program arguments or else a single string'.
import pathlib
import subprocess
in_file_1 = pathlib.Path.cwd() / "folder2" / "folder3" / "whatever.exe"
p = subprocess.Popen(str(in_file_1), shell = True)
I would expect to see the whatever.exe process running on the administrator tasks but the process is not started. How can I achieve that? Is there something I am ingoring? Should I just give the relative path from where the python script is saved?

You are confusing the current working directory, which is what pathlib.Path.cwd() returns, with the script's location.
If you want the script's dir, you can use __file__, for instance like this:
import pathlib
cwd = pathlib.Path.cwd()
script_file = pathlib.Path(__file__)
script_location = script_file.parent
print("The current dir is", pathlib.Path.cwd())
print("The current script is", script_file)
print("The current script's dir is", script_file.parent)
which will return:
The current dir is /home/nicoco
The current script is /tmp/so.py
The current script's dir is /tmp

Related

import image in python, my program cant work if i move program folder in different place if I want it to run, I have to change my code

i have problem on my program, I import images, and it works but behind that success there is something missing for me.
Check out the following code snippet:
# python 3
from PIL import Image
from PIL import ImageTk
pathdesign_img = "D:/Python/Project1/image/design/
self.logo_Tbar_img = ImageTk.PhotoImage(Image.open(pathdesign_img+'Mlogo.jpg'))
self.logo_Tbar = tk.Label(self.bar_Tbar, image=self.logo_Tbar_img, bg="#DA291C")
self.logo_Tbar.pack(side=tk.LEFT, fill=tk.BOTH)
The code works but when I want to move all my program folders to diffrent place example: C:\User\. My program cannot run and if I want it to run, I have to change pathdesign_img = "C:/User/....". Is there any code that I need to change or add, so that my program can run in any folder, without having to change pathdesign_img
Yeah, paths relative to your app's directory are the correct solution, but when passing them forward to be used it is always advisable to use absolute paths.
So, you use absolute paths relative to your app's directory.
It can be easy as:
import os
dirpath = os.path.abspath("images")
# os.path.abspath() will return the absolute path of the directory images
# that resides in the current working directory which you can discover with
# os.getcwd() and manipulate using os.chdir()
# Note that the current working directory may be manipulated from the OS.
# In the Windows's case you can specify it under properties of the shortcut
# and/or the executable. By the default it is the same directory where
# the executable lives, in this case, your script.
imagepath = os.path.join(dirpath, "<some_image>.jpg")
That is how it should be done. It is cross-platform, good practice, and will not give you trouble with paths.
However, if you are planning to bundle your app into a e.g. EXE, you need to be much craftier than that. That's because the *.exe bundled app is actually a ZIP file with some additions.
In this case the imagepath will look like:
>>> print (imagepath)
C:\Program Files\Yours_app_folder\yourapp.exe\images\your_image.jpg
which, of course is an invalid path for the OS. In these cases I do the following.
I create a module called whereiam or whereami (the name depends on how I feel I guess) in which I put a var or function that gets me the correct path to my app's directory. E.g.
import os, sys
def root ():
# If the app is only a script, this will result in mydir
# being a path to the directory where the 'whereiam' module lives:
me = os.path.abspath(__file__)
mydir = os.path.dirname(me)
# If the app is bundled then sys.executable points to it instead
# of Python interpreter, so first check for that
if mydir.startswith(sys.executable):
# Then we first get the directory where our app lives:
mydir = os.path.dirname(sys.executable)
# And if our whereiam is in a subdirectory, we find it by excluding
# the executable's filename from the path:
# by appending the rest to the mydir
l = len(sys.executable)
mydir = os.path.join(mydir.rstrip(os.sep), me[l:].lstrip(os.sep))
return mydir
Then in your main module you just do:
import whereiam
import os
dirpath = whereiam.root()
images = os.path.join(dirpath, "images")
imagepath = os.path.join(images, "<your_image>.jpg")
# And you can then open imagepath with PIL or whatever being sure that it will be found if it is there
Yes, it should be possible. I assume that your python-file or jupyter-notebook is in the folder "D:/Python/Project1", whereas your image is in the folder "D:/Python/Project1/image/design". Then you could do:
pathdesign_img = "image/design/"
In short, what this does: In the folder that you are already in, it searches for a folder called "image" and in that folder for a sub-folder called "design".

Python - variable for the scriptroot [duplicate]

I would like to see what is the best way to determine the current script directory in Python.
I discovered that, due to the many ways of calling Python code, it is hard to find a good solution.
Here are some problems:
__file__ is not defined if the script is executed with exec, execfile
__module__ is defined only in modules
Use cases:
./myfile.py
python myfile.py
./somedir/myfile.py
python somedir/myfile.py
execfile('myfile.py') (from another script, that can be located in another directory and that can have another current directory.
I know that there is no perfect solution, but I'm looking for the best approach that solves most of the cases.
The most used approach is os.path.dirname(os.path.abspath(__file__)) but this really doesn't work if you execute the script from another one with exec().
Warning
Any solution that uses current directory will fail, this can be different based on the way the script is called or it can be changed inside the running script.
os.path.dirname(os.path.abspath(__file__))
is indeed the best you're going to get.
It's unusual to be executing a script with exec/execfile; normally you should be using the module infrastructure to load scripts. If you must use these methods, I suggest setting __file__ in the globals you pass to the script so it can read that filename.
There's no other way to get the filename in execed code: as you note, the CWD may be in a completely different place.
If you really want to cover the case that a script is called via execfile(...), you can use the inspect module to deduce the filename (including the path). As far as I am aware, this will work for all cases you listed:
filename = inspect.getframeinfo(inspect.currentframe()).filename
path = os.path.dirname(os.path.abspath(filename))
In Python 3.4+ you can use the simpler pathlib module:
from inspect import currentframe, getframeinfo
from pathlib import Path
filename = getframeinfo(currentframe()).filename
parent = Path(filename).resolve().parent
You can also use __file__ (when it's available) to avoid the inspect module altogether:
from pathlib import Path
parent = Path(__file__).resolve().parent
#!/usr/bin/env python
import inspect
import os
import sys
def get_script_dir(follow_symlinks=True):
if getattr(sys, 'frozen', False): # py2exe, PyInstaller, cx_Freeze
path = os.path.abspath(sys.executable)
else:
path = inspect.getabsfile(get_script_dir)
if follow_symlinks:
path = os.path.realpath(path)
return os.path.dirname(path)
print(get_script_dir())
It works on CPython, Jython, Pypy. It works if the script is executed using execfile() (sys.argv[0] and __file__ -based solutions would fail here). It works if the script is inside an executable zip file (/an egg). It works if the script is "imported" (PYTHONPATH=/path/to/library.zip python -mscript_to_run) from a zip file; it returns the archive path in this case. It works if the script is compiled into a standalone executable (sys.frozen). It works for symlinks (realpath eliminates symbolic links). It works in an interactive interpreter; it returns the current working directory in this case.
The os.path... approach was the 'done thing' in Python 2.
In Python 3, you can find directory of script as follows:
from pathlib import Path
script_path = Path(__file__).parent
Note: this answer is now a package (also with safe relative importing capabilities)
https://github.com/heetbeet/locate
$ pip install locate
$ python
>>> from locate import this_dir
>>> print(this_dir())
C:/Users/simon
For .py scripts as well as interactive usage:
I frequently use the directory of my scripts (for accessing files stored alongside them), but I also frequently run these scripts in an interactive shell for debugging purposes. I define this_dir as:
When running or importing a .py file, the file's base directory. This is always the correct path.
When running an .ipyn notebook, the current working directory. This is always the correct path, since Jupyter sets the working directory as the .ipynb base directory.
When running in a REPL, the current working directory. Hmm, what is the actual "correct path" when the code is detached from a file? Rather, make it your responsibility to change into the "correct path" before invoking the REPL.
Python 3.4 (and above):
from pathlib import Path
this_dir = Path(globals().get("__file__", "./_")).absolute().parent
Python 2 (and above):
import os
this_dir = os.path.dirname(os.path.abspath(globals().get("__file__", "./_")))
Explanation:
globals() returns all the global variables as a dictionary.
.get("__file__", "./_") returns the value from the key "__file__" if it exists in globals(), otherwise it returns the provided default value "./_".
The rest of the code just expands __file__ (or "./_") into an absolute filepath, and then returns the filepath's base directory.
Alternative:
If you know for certain that __file__ is available to your surrounding code, you can simplify to this:
>= Python 3.4: this_dir = Path(__file__).absolute().parent
>= Python 2: this_dir = os.path.dirname(os.path.abspath(__file__))
Would
import os
cwd = os.getcwd()
do what you want? I'm not sure what exactly you mean by the "current script directory". What would the expected output be for the use cases you gave?
Just use os.path.dirname(os.path.abspath(__file__)) and examine very carefully whether there is a real need for the case where exec is used. It could be a sign of troubled design if you are not able to use your script as a module.
Keep in mind Zen of Python #8, and if you believe there is a good argument for a use-case where it must work for exec, then please let us know some more details about the background of the problem.
First.. a couple missing use-cases here if we're talking about ways to inject anonymous code..
code.compile_command()
code.interact()
imp.load_compiled()
imp.load_dynamic()
imp.load_module()
__builtin__.compile()
loading C compiled shared objects? example: _socket?)
But, the real question is, what is your goal - are you trying to enforce some sort of security? Or are you just interested in whats being loaded.
If you're interested in security, the filename that is being imported via exec/execfile is inconsequential - you should use rexec, which offers the following:
This module contains the RExec class,
which supports r_eval(), r_execfile(),
r_exec(), and r_import() methods, which
are restricted versions of the standard
Python functions eval(), execfile() and
the exec and import statements. Code
executed in this restricted environment
will only have access to modules and
functions that are deemed safe; you can
subclass RExec add or remove capabilities as
desired.
However, if this is more of an academic pursuit.. here are a couple goofy approaches that you
might be able to dig a little deeper into..
Example scripts:
./deep.py
print ' >> level 1'
execfile('deeper.py')
print ' << level 1'
./deeper.py
print '\t >> level 2'
exec("import sys; sys.path.append('/tmp'); import deepest")
print '\t << level 2'
/tmp/deepest.py
print '\t\t >> level 3'
print '\t\t\t I can see the earths core.'
print '\t\t << level 3'
./codespy.py
import sys, os
def overseer(frame, event, arg):
print "loaded(%s)" % os.path.abspath(frame.f_code.co_filename)
sys.settrace(overseer)
execfile("deep.py")
sys.exit(0)
Output
loaded(/Users/synthesizerpatel/deep.py)
>> level 1
loaded(/Users/synthesizerpatel/deeper.py)
>> level 2
loaded(/Users/synthesizerpatel/<string>)
loaded(/tmp/deepest.py)
>> level 3
I can see the earths core.
<< level 3
<< level 2
<< level 1
Of course, this is a resource-intensive way to do it, you'd be tracing
all your code.. Not very efficient. But, I think it's a novel approach
since it continues to work even as you get deeper into the nest.
You can't override 'eval'. Although you can override execfile().
Note, this approach only coveres exec/execfile, not 'import'.
For higher level 'module' load hooking you might be able to use use
sys.path_hooks (Write-up courtesy of PyMOTW).
Thats all I have off the top of my head.
Here is a partial solution, still better than all published ones so far.
import sys, os, os.path, inspect
#os.chdir("..")
if '__file__' not in locals():
__file__ = inspect.getframeinfo(inspect.currentframe())[0]
print os.path.dirname(os.path.abspath(__file__))
Now this works will all calls but if someone use chdir() to change the current directory, this will also fail.
Notes:
sys.argv[0] is not going to work, will return -c if you execute the script with python -c "execfile('path-tester.py')"
I published a complete test at https://gist.github.com/1385555 and you are welcome to improve it.
To get the absolute path to the directory containing the current script you can use:
from pathlib import Path
absDir = Path(__file__).parent.resolve()
Please note the .resolve() call is required, because that is the one making the path absolute. Without resolve(), you would obtain something like '.'.
This solution uses pathlib, which is part of Python's stdlib since v3.4 (2014). This is preferrable compared to other solutions using os.
The official pathlib documentation has a useful table mapping the old os functions to the new ones: https://docs.python.org/3/library/pathlib.html#correspondence-to-tools-in-the-os-module
This should work in most cases:
import os,sys
dirname=os.path.dirname(os.path.realpath(sys.argv[0]))
Hopefully this helps:-
If you run a script/module from anywhere you'll be able to access the __file__ variable which is a module variable representing the location of the script.
On the other hand, if you're using the interpreter you don't have access to that variable, where you'll get a name NameError and os.getcwd() will give you the incorrect directory if you're running the file from somewhere else.
This solution should give you what you're looking for in all cases:
from inspect import getsourcefile
from os.path import abspath
abspath(getsourcefile(lambda:0))
I haven't thoroughly tested it but it solved my problem.
If __file__ is available:
# -- script1.py --
import os
file_path = os.path.abspath(__file__)
print(os.path.dirname(file_path))
For those we want to be able to run the command from the interpreter or get the path of the place you're running the script from:
# -- script2.py --
import os
print(os.path.abspath(''))
This works from the interpreter.
But when run in a script (or imported) it gives the path of the place where
you ran the script from, not the path of directory containing
the script with the print.
Example:
If your directory structure is
test_dir (in the home dir)
├── main.py
└── test_subdir
├── script1.py
└── script2.py
with
# -- main.py --
import script1.py
import script2.py
The output is:
~/test_dir/test_subdir
~/test_dir
As previous answers require you to import some module, I thought that I would write one answer that doesn't. Use the code below if you don't want to import anything.
this_dir = '/'.join(__file__.split('/')[:-1])
print(this_dir)
If the script is on /path/to/script.py then this would print /path/to. Note that this will throw error on terminal as no file is executed. This basically parse the directory from __file__ removing the last part of it. In this case /script.py is removed to produce the output /path/to.
print(__import__("pathlib").Path(__file__).parent)

Set current directory when running a Python project [duplicate]

I used to open files that were in the same directory as the currently running Python script by simply using a command like:
open("Some file.txt", "r")
However, I discovered that when the script was run in Windows by double-clicking it, it would try to open the file from the wrong directory.
Since then I've used a command of the form
open(os.path.join(sys.path[0], "Some file.txt"), "r")
whenever I wanted to open a file. This works for my particular usage, but I'm not sure if sys.path[0] might fail in some other use case.
So my question is: What is the best and most reliable way to open a file that's in the same directory as the currently running Python script?
Here's what I've been able to figure out so far:
os.getcwd() and os.path.abspath('') return the "current working directory", not the script directory.
os.path.dirname(sys.argv[0]) and os.path.dirname(__file__) return the path used to call the script, which may be relative or even blank (if the script is in the cwd). Also, __file__ does not exist when the script is run in IDLE or PythonWin.
sys.path[0] and os.path.abspath(os.path.dirname(sys.argv[0])) seem to return the script directory. I'm not sure if there's any difference between these two.
Edit:
I just realized that what I want to do would be better described as "open a file in the same directory as the containing module". In other words, if I import a module I wrote that's in another directory, and that module opens a file, I want it to look for the file in the module's directory. I don't think anything I've found is able to do that...
I always use:
__location__ = os.path.realpath(
os.path.join(os.getcwd(), os.path.dirname(__file__)))
The join() call prepends the current working directory, but the documentation says that if some path is absolute, all other paths left of it are dropped. Therefore, getcwd() is dropped when dirname(__file__) returns an absolute path.
Also, the realpath call resolves symbolic links if any are found. This avoids troubles when deploying with setuptools on Linux systems (scripts are symlinked to /usr/bin/ -- at least on Debian).
You may the use the following to open up files in the same folder:
f = open(os.path.join(__location__, 'bundled-resource.jpg'))
# ...
I use this to bundle resources with several Django application on both Windows and Linux and it works like a charm!
On Python 3.4, the pathlib module was added, and the following code will reliably open a file in the same directory as the current script:
from pathlib import Path
p = Path(__file__).with_name('file.txt')
with p.open('r') as f:
print(f.read())
If you instead need the file path as a string for some open-like API, you can get it using absolute():
p = Path(__file__).with_name('file.txt')
filename = p.absolute()
NOTE: Python REPLs such as running the python command without a target or ipython do not expose __file__.
To quote from the Python documentation:
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.
If you are running the script from the terminal, sys.path[0] is what you are looking for.
However, if you have:
barpath/bar.py
import foopath.foo
foopath/foo.py
print sys.path[0] # you get barpath
So watch out!
Ok here is what I do
sys.argv is always what you type into the terminal or use as the file path when executing it with python.exe or pythonw.exe
For example you can run the file text.py several ways, they each give you a different answer they always give you the path that python was typed.
C:\Documents and Settings\Admin>python test.py
sys.argv[0]: test.py
C:\Documents and Settings\Admin>python "C:\Documents and Settings\Admin\test.py"
sys.argv[0]: C:\Documents and Settings\Admin\test.py
Ok so know you can get the file name, great big deal, now to get the application directory you can know use os.path, specifically abspath and dirname
import sys, os
print os.path.dirname(os.path.abspath(sys.argv[0]))
That will output this:
C:\Documents and Settings\Admin\
it will always output this no matter if you type python test.py or python "C:\Documents and Settings\Admin\test.py"
The problem with using __file__
Consider these two files
test.py
import sys
import os
def paths():
print "__file__: %s" % __file__
print "sys.argv: %s" % sys.argv[0]
a_f = os.path.abspath(__file__)
a_s = os.path.abspath(sys.argv[0])
print "abs __file__: %s" % a_f
print "abs sys.argv: %s" % a_s
if __name__ == "__main__":
paths()
import_test.py
import test
import sys
test.paths()
print "--------"
print __file__
print sys.argv[0]
Output of "python test.py"
C:\Documents and Settings\Admin>python test.py
__file__: test.py
sys.argv: test.py
abs __file__: C:\Documents and Settings\Admin\test.py
abs sys.argv: C:\Documents and Settings\Admin\test.py
Output of "python test_import.py"
C:\Documents and Settings\Admin>python test_import.py
__file__: C:\Documents and Settings\Admin\test.pyc
sys.argv: test_import.py
abs __file__: C:\Documents and Settings\Admin\test.pyc
abs sys.argv: C:\Documents and Settings\Admin\test_import.py
--------
test_import.py
test_import.py
So as you can see file gives you always the python file it is being run from, where as sys.argv[0] gives you the file that you ran from the interpreter always. Depending on your needs you will need to choose which one best fits your needs.
I commonly use the following. It works for testing and probably other use cases as well.
with open(os.path.join(os.path.dirname(__file__), 'some_file.txt'), 'r') as f:
This answer is recommended in https://stackoverflow.com/questions/10174211/how-to-make-an-always-relative-to-current-module-file-path

Can you try this simple approach just like this:
import os
my_local_file = os.path.join(os.path.dirname(__file__), 'some_file.txt')
f = open(my_local_file, "r")
my_local_data = f.read()
Because I get an error trying to use __file__ or sys.argv[0] from emacs I do it that way:
from inspect import getfile
from pathlib import Path
script_path = getfile(lambda: None)
print(script_path)
parent_path = Path(script_path).parent
print(parent_path)
with open(parent_path/'Some file.txt', 'r') as obFile:
print(obFile.read())
After trying all of this solutions, I still had different problems. So what I found the simplest way was to create a python file: config.py, with a dictionary containing the file's absolute path and import it into the script.
something like
import config as cfg
import pandas as pd
pd.read_csv(cfg.paths['myfilepath'])
where config.py has inside:
paths = {'myfilepath': 'home/docs/...'}
It is not automatic but it is a good solution when you have to work in different directory or different machines.
I'd do it this way:
from os.path import abspath, exists
f_path = abspath("fooabar.txt")
if exists(f_path):
with open(f_path) as f:
print f.read()
The above code builds an absolute path to the file using abspath and is equivalent to using normpath(join(os.getcwd(), path)) [that's from the pydocs]. It then checks if that file actually exists and then uses a context manager to open it so you don't have to remember to call close on the file handle. IMHO, doing it this way will save you a lot of pain in the long run.

(Python) Why do I always have to type absolute paths in file functions?

For instance, if I have:
C:\42\main.py
and
C:\42\info.txt
and I want to read info.txt from main.py, I have to input "C:\42\info.txt" instad of just "info.txt".
Is it supposed to be like that?
If not, how can I fix it?
You can specify paths relative to where your script is. I do it all the time when writing unittests.
Every python file has a special attribute -- __file__ -- that stores the path to that file.
py_file= os.path.abspath(__file__) # path to main.py
py_dir = os.path.dirname(py_file) # path to the parent dir of main.py
txt_file = os.path.join(py_dir, 'info.txt') # path to info.txt
It is supposed to be like that. Relative paths are relative to the process's current working directory, not the directory that your script resides in.
Rather than hardcoding it, you can find the script's path using sys.path[0], and either chdir to it or use it directly in the filename:
os.path.join(sys.path[0], 'info.txt')

How do I get the path and name of the file that is currently executing?

I have scripts calling other script files but I need to get the filepath of the file that is currently running within the process.
For example, let's say I have three files. Using execfile:
script_1.py calls script_2.py.
In turn, script_2.py calls script_3.py.
How can I get the file name and path of script_3.py, from code within script_3.py, without having to pass that information as arguments from script_2.py?
(Executing os.getcwd() returns the original starting script's filepath not the current file's.)
__file__
as others have said. You may also want to use os.path.realpath to eliminate symlinks:
import os
os.path.realpath(__file__)
p1.py:
execfile("p2.py")
p2.py:
import inspect, os
print (inspect.getfile(inspect.currentframe())) # script filename (usually with path)
print (os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))) # script directory
Update 2018-11-28:
Here is a summary of experiments with Python 2 and 3. With
main.py - runs foo.py
foo.py - runs lib/bar.py
lib/bar.py - prints filepath expressions
| Python | Run statement | Filepath expression |
|--------+---------------------+----------------------------------------|
| 2 | execfile | os.path.abspath(inspect.stack()[0][1]) |
| 2 | from lib import bar | __file__ |
| 3 | exec | (wasn't able to obtain it) |
| 3 | import lib.bar | __file__ |
For Python 2, it might be clearer to switch to packages so can use from lib import bar - just add empty __init__.py files to the two folders.
For Python 3, execfile doesn't exist - the nearest alternative is exec(open(<filename>).read()), though this affects the stack frames. It's simplest to just use import foo and import lib.bar - no __init__.py files needed.
See also Difference between import and execfile
Original Answer:
Here is an experiment based on the answers in this thread - with Python 2.7.10 on Windows.
The stack-based ones are the only ones that seem to give reliable results. The last two have the shortest syntax, i.e. -
print os.path.abspath(inspect.stack()[0][1]) # C:\filepaths\lib\bar.py
print os.path.dirname(os.path.abspath(inspect.stack()[0][1])) # C:\filepaths\lib
Here's to these being added to sys as functions! Credit to #Usagi and #pablog
Based on the following three files, and running main.py from its folder with python main.py (also tried execfiles with absolute paths and calling from a separate folder).
C:\filepaths\main.py: execfile('foo.py')
C:\filepaths\foo.py: execfile('lib/bar.py')
C:\filepaths\lib\bar.py:
import sys
import os
import inspect
print "Python " + sys.version
print
print __file__ # main.py
print sys.argv[0] # main.py
print inspect.stack()[0][1] # lib/bar.py
print sys.path[0] # C:\filepaths
print
print os.path.realpath(__file__) # C:\filepaths\main.py
print os.path.abspath(__file__) # C:\filepaths\main.py
print os.path.basename(__file__) # main.py
print os.path.basename(os.path.realpath(sys.argv[0])) # main.py
print
print sys.path[0] # C:\filepaths
print os.path.abspath(os.path.split(sys.argv[0])[0]) # C:\filepaths
print os.path.dirname(os.path.abspath(__file__)) # C:\filepaths
print os.path.dirname(os.path.realpath(sys.argv[0])) # C:\filepaths
print os.path.dirname(__file__) # (empty string)
print
print inspect.getfile(inspect.currentframe()) # lib/bar.py
print os.path.abspath(inspect.getfile(inspect.currentframe())) # C:\filepaths\lib\bar.py
print os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) # C:\filepaths\lib
print
print os.path.abspath(inspect.stack()[0][1]) # C:\filepaths\lib\bar.py
print os.path.dirname(os.path.abspath(inspect.stack()[0][1])) # C:\filepaths\lib
print
I think this is cleaner:
import inspect
print inspect.stack()[0][1]
and gets the same information as:
print inspect.getfile(inspect.currentframe())
Where [0] is the current frame in the stack (top of stack) and [1] is for the file name, increase to go backwards in the stack i.e.
print inspect.stack()[1][1]
would be the file name of the script that called the current frame. Also, using [-1] will get you to the bottom of the stack, the original calling script.
import os
os.path.dirname(__file__) # relative directory path
os.path.abspath(__file__) # absolute file path
os.path.basename(__file__) # the file name only
The suggestions marked as best are all true if your script consists of only one file.
If you want to find out the name of the executable (i.e. the root file passed to the python interpreter for the current program) from a file that may be imported as a module, you need to do this (let's assume this is in a file named foo.py):
import inspect
print inspect.stack()[-1][1]
Because the last thing ([-1]) on the stack is the first thing that went into it (stacks are LIFO/FILO data structures).
Then in file bar.py if you import foo it'll print bar.py, rather than foo.py, which would be the value of all of these:
__file__
inspect.getfile(inspect.currentframe())
inspect.stack()[0][1]
Since Python 3 is fairly mainstream, I wanted to include a pathlib answer, as I believe that it is probably now a better tool for accessing file and path information.
from pathlib import Path
current_file: Path = Path(__file__).resolve()
If you are seeking the directory of the current file, it is as easy as adding .parent to the Path() statement:
current_path: Path = Path(__file__).parent.resolve()
It's not entirely clear what you mean by "the filepath of the file that is currently running within the process".
sys.argv[0] usually contains the location of the script that was invoked by the Python interpreter.
Check the sys documentation for more details.
As #Tim and #Pat Notz have pointed out, the __file__ attribute provides access to
the file from which the module was
loaded, if it was loaded from a file
import os
print os.path.basename(__file__)
this will give us the filename only. i.e. if abspath of file is c:\abcd\abc.py then 2nd line will print abc.py
I have a script that must work under windows environment.
This code snipped is what I've finished with:
import os,sys
PROJECT_PATH = os.path.abspath(os.path.split(sys.argv[0])[0])
it's quite a hacky decision. But it requires no external libraries and it's the most important thing in my case.
Try this,
import os
os.path.dirname(os.path.realpath(__file__))
import os
os.path.dirname(os.path.abspath(__file__))
No need for inspect or any other library.
This worked for me when I had to import a script (from a different directory then the executed script), that used a configuration file residing in the same folder as the imported script.
The __file__ attribute works for both the file containing the main execution code as well as imported modules.
See https://web.archive.org/web/20090918095828/http://pyref.infogami.com/__file__
import sys
print sys.path[0]
this would print the path of the currently executing script
I think it's just __file__ Sounds like you may also want to checkout the inspect module.
You can use inspect.stack()
import inspect,os
inspect.stack()[0] => (<frame object at 0x00AC2AC0>, 'g:\\Python\\Test\\_GetCurrentProgram.py', 15, '<module>', ['print inspect.stack()[0]\n'], 0)
os.path.abspath (inspect.stack()[0][1]) => 'g:\\Python\\Test\\_GetCurrentProgram.py'
import sys
print sys.argv[0]
print(__file__)
print(__import__("pathlib").Path(__file__).parent)
This should work:
import os,sys
filename=os.path.basename(os.path.realpath(sys.argv[0]))
dirname=os.path.dirname(os.path.realpath(sys.argv[0]))
Here is what I use so I can throw my code anywhere without issue. __name__ is always defined, but __file__ is only defined when the code is run as a file (e.g. not in IDLE/iPython).
if '__file__' in globals():
self_name = globals()['__file__']
elif '__file__' in locals():
self_name = locals()['__file__']
else:
self_name = __name__
Alternatively, this can be written as:
self_name = globals().get('__file__', locals().get('__file__', __name__))
To get directory of executing script
print os.path.dirname( inspect.getfile(inspect.currentframe()))
I used the approach with __file__
os.path.abspath(__file__)
but there is a little trick, it returns the .py file
when the code is run the first time,
next runs give the name of *.pyc file
so I stayed with:
inspect.getfile(inspect.currentframe())
or
sys._getframe().f_code.co_filename
I wrote a function which take into account eclipse debugger and unittest.
It return the folder of the first script you launch. You can optionally specify the __file__ var, but the main thing is that you don't have to share this variable across all your calling hierarchy.
Maybe you can handle others stack particular cases I didn't see, but for me it's ok.
import inspect, os
def getRootDirectory(_file_=None):
"""
Get the directory of the root execution file
Can help: http://stackoverflow.com/questions/50499/how-do-i-get-the-path-and-name-of-the-file-that-is-currently-executing
For eclipse user with unittest or debugger, the function search for the correct folder in the stack
You can pass __file__ (with 4 underscores) if you want the caller directory
"""
# If we don't have the __file__ :
if _file_ is None:
# We get the last :
rootFile = inspect.stack()[-1][1]
folder = os.path.abspath(rootFile)
# If we use unittest :
if ("/pysrc" in folder) & ("org.python.pydev" in folder):
previous = None
# We search from left to right the case.py :
for el in inspect.stack():
currentFile = os.path.abspath(el[1])
if ("unittest/case.py" in currentFile) | ("org.python.pydev" in currentFile):
break
previous = currentFile
folder = previous
# We return the folder :
return os.path.dirname(folder)
else:
# We return the folder according to specified __file__ :
return os.path.dirname(os.path.realpath(_file_))
Simplest way is:
in script_1.py:
import subprocess
subprocess.call(['python3',<path_to_script_2.py>])
in script_2.py:
sys.argv[0]
P.S.: I've tried execfile, but since it reads script_2.py as a string, sys.argv[0] returned <string>.
The following returns the path where your current main script is located at. I tested this with Linux, Win10, IPython and Jupyter Lab. I needed a solution that works for local Jupyter notebooks as well.
import builtins
import os
import sys
def current_dir():
if "get_ipython" in globals() or "get_ipython" in dir(builtins):
# os.getcwd() is PROBABLY the dir that hosts the active notebook script.
# See also https://github.com/ipython/ipython/issues/10123
return os.getcwd()
else:
return os.path.abspath(os.path.dirname(sys.argv[0]))
Finding the home directory of the path in which your Python script resides
As an addendum to the other answers already here (and not answering the OP's question, since other answers already do that), if the path to your script is /home/gabriel/GS/dev/eRCaGuy_dotfiles/useful_scripts/cpu_logger.py, and you wish to obtain the home directory part of that path, which is /home/gabriel, you can do this:
import os
# Obtain the home dir of the user in whose home directory this script resides
script_path_list = os.path.normpath(__file__).split(os.sep)
home_dir = os.path.join("/", script_path_list[1], script_path_list[2])
To help make sense of this, here are the paths for __file__, script_path_list, and home_dir. Notice that script_path_list is a list of the path components, with the first element being an empty string since it originally contained the / root dir path separator for this Linux path:
__file__ = /home/gabriel/GS/dev/eRCaGuy_dotfiles/useful_scripts/cpu_logger.py
script_path_list = ['', 'home', 'gabriel', 'GS', 'dev', 'eRCaGuy_dotfiles', 'useful_scripts', 'cpu_logger.py']
home_dir = /home/gabriel
Source:
Python: obtain the path to the home directory of the user in whose directory the script being run is located [duplicate]

Categories