Working on OS X Lion, I'm trying to open a file in my python-program from anywhere in the terminal. I have set the following function in my .bash_profile:
function testprogram() {python ~/.folder/.testprogram.py}
This way I can(in the terminal) run my testprogram from a different directory than my ~/.
Now, if I'm in my home directory, and run the program, the following would work
infile = open("folder2/test.txt", "r+")
However, if I'm in a different directory from my home-folder and write "testprogram" in the terminal, the program starts but is unable to find the file test.txt.
Is there any way to always have python open the file from the same location unaffected of where i run the program from?
If you want to make it multiplatform I would recommend
import os
open(os.path.join(os.path.expanduser('~'),'rest/of/path/to.file'))
Use the tilde to represent the home folder, just as you would in the .bash_profile, and use os.path.expanduser.
import os
infile = open(os.path.expanduser("~/folder2/test.txt"), "r+")
This is no different than referring to a file via anything else besides Python, you need to use an absolute path rather than a relative one.
If you'd like to refer to files relative to the location of the script, you can also use the __file__ attribute in your module to get the location of the currently running module.
Also, rather than using a shell function, just give your script a shebang line (#!/usr/bin/env python), chmod +x it, and put it someplace on your PATH.
You could simply run the function in a subshell so you can cd home before running it:
function testprogram() { (
cd && python .folder/.testprogram.py
) }
In python sys.argv[0] will be set to the path of the script (if known). You can use this plus the functions in os.path to access files relative to the directory containing the script. For example
import sys, os.path
script_path = sys.argv[0]
script_dir = os.path.dirname(script_path)
def script_relative(filename):
return os.path.join(script_dir, filename)
infile = open(script_relative("folder2/test.txt"), "r+")
David Robinson points out that sys.argv[0] may not be a full pathname. Instead of using sys.argv[0] you can use __file__ if this is the case.
Use either full path like
/path/to/my/folder2/test.txt
or abbreviated one
~/folder2/test.txt
Related
So when I try to find the path from the cmd with where azuredatastudio, I get the path. When I go in Python and do print(os.environ), I get many defined paths, but not this from the upper command in cmd.
How to get in this example azuredatastudio path from Python and where is it stored?
The WHERE command is roughly equivalent to the UNIX 'which' command. By default, the search is done in the current directory and in the PATH.
Source: https://ss64.com/nt/where.html
So you'll have to explicitly look at the paths in the PATH environment variable: os.environ['PATH']. You'll find an implementation in this question here for example: Test if executable exists in Python?
Also, you should be able to just run the command from Python:
from subprocess import check_output
path = check_output(["where", "azuredatastudio"])
print(path)
A easy way to do this is:
import os
os.system("where azuredatastudio")
or if you want to save it in a variable.
import subprocess
process = subprocess.Popen("where azuredatastudio",stdout=subprocess.PIPE)
print(process.stdout.readline())
When i run in terminal i get the [Errno 2] No such file or directory error, but when i use debug mode it works.
the error occurs here,
list = open(filename, "r")
the code also works with IDLE
Your debugger is most likely running in a different location than your terminal. cd your terminal to where the file is located, or try using the absolute path instead of a relative one.
If you add these few lines in your code and run it using your IDE or Terminal, you'll notice the difference:
import os
curdir = os.getcwd()
print('My current directory is {}'.format(curdir))
fullpath_to_filename = os.path.join(curdir, filename)
print('When I run `open(filename)`, python sees: {}'.format(fullpath_to_filename))
print('This filepath is {}valid'.format('' if os.path.exists(fullpath_to_filename) else 'not '))
You'll likely experience something similar to below:
# on IDE:
My current directory is c:\Users\me\Projects\
When I run `open(filename)`, python sees: c:\Users\me\Projects\test.txt
This filepath is valid
# on Terminal:
My current directory is c:\Programs\Python38\
When I run `open(filename)`, python sees: c:\Programs\Python38\test.txt
This filepath is not valid
Solution: use absolute path for your filename, or os.chdir(...) to the correct parent path before location filename. I would recommend the former to avoid managing directories.
How can I write a Python program that runs all Python scripts in the current folder? The program should run in Linux, Windows and any other OS in which python is installed.
Here is what I tried:
import glob, importlib
for file in glob.iglob("*.py"):
importlib.import_module(file)
This returns an error: ModuleNotFoundError: No module named 'agents.py'; 'agents' is not a package
(here agents.py is one of the files in the folder; it is indeed not a package and not intended to be a package - it is just a script).
If I change the last line to:
importlib.import_module(file.replace(".py",""))
then I get no error, but also the scripts do not run.
Another attempt:
import glob, os
for file in glob.iglob("*.py"):
os.system(file)
This does not work on Windows - it tries to open each file in Notepad.
You need to specify that you are running the script through the command line. To do this you need to add python3 plus the name of the file that you are running. The following code should work
import os
import glob
for file in glob.iglob("*.py"):
os.system("python3 " + file)
If you are using a version other than python3, just change the argument from python3 to python
Maybe you can make use of the subprocess module; this question shows a few options.
Your code could look like this:
import os
import subprocess
base_path = os.getcwd()
print('base_path', base_path)
# TODO: this might need to be 'python3' in some cases
python_executable = 'python'
print('python_executable', python_executable)
py_file_list = []
for dir_path, _, file_name_list in os.walk(base_path):
for file_name in file_name_list:
if file_name.endswith('.csv'):
# add full path, not just file_name
py_file_list.append(
os.path.join(dir_path, file_name))
print('PY files that were found:')
for i, file_path in enumerate(py_file_list):
print(' {:3d} {}'.format(i, file_path))
# call script
subprocess.run([python_executable, file_path])
Does that work for you?
Note that the docs for os.system() even suggest using subprocess instead:
The subprocess module provides more powerful facilities for spawning new processes and retrieving their results; using that module is preferable to using this function.
If you have control over the content of the scripts, perhaps you might consider using a plugin technique, this would bring the problem more into the Python domain and thus makes it less platform dependent. Take a look at pyPlugin as an example.
This way you could run each "plugin" from within the original process, or using the Python::multiprocessing library you could still seamlessly use sub-processes.
I have a python 3 code:
system_name = 'myName'
path_perf_folder = os.path.dirname(sys.argv[0]) + '/' + system_name + '_test/'
try:
coriginal_umask = os.umask(0)
os.makedirs(path_perf_folder, 0o755)
finally:
os.umask(original_umask)
The code runs perfectly from python console (running directly os.makedirs command without permission and umask stuff), but when I run from Linux Centos 7.0 terminal or MacOS 10.14.1 terminal it does not work.
I have tried different permissions al well (0o770 and 0o777) but all the time my error is:
File "performance_maker.py", line 130, in <module>
os.makedirs(path_perf_folder, 0o755)
File "/shared/centos7/python/3.7.0/lib/python3.7/os.py", line 221, in
makedirs
mkdir(name, mode)
PermissionError: [Errno 13] Permission denied: '/myName_test/'
The umask part I c/p from a stackoverflow question but it does not work for me
here is the link
Thanks!
os.path.dirname(sys.argv[0]) will only be a nonempty string if sys.argv[0] has a path separator (i.e. '/' for unix-like systems) character in it. Using string operations to construct the path like you do means that you'll try to create the directory under /, which you probably don't have write access to. Instead, you should use os.path.join to construct your path, so that empty strings get handled properly and you get the relative path you want.
When run from the command line, your script is probably getting only the filename of the script, not the full path. Therefore, when run at the command line, your script is attempting to mkdir in the root ("/") folder. See below for a quick script you can run to see how your system works.
import os, sys
dirname_out = os.path.dirname(sys.argv[0])
print('sys.argv[0] is {}'.format(sys.argv[0])) # See difference from REPL and when run as script
print('cwd is {}'.format(os.getcwd())) # Might be what you want
print('dirname is: {}'.format(dirname_out))
print('dirname of cwd is: {}'.format(os.path.dirname(os.getcwd()))) # Not recommended
Depending on how you want your script to operate, your solution will vary. I am not sure of your desired outcome as you did not supply the input when you executed your script.
If you want to run the script and always make the new directory in the same directory you ran the script, you probably want to us "os.getcwd()" for creating the base dir.
If you want to provide the location to create the directory, then you probably want to pass the directory to the script by checking, parsing, and constructing from sys.argv[1].
I am trying to rename a set of pdf files in my desktop using a simple python script. I am somehow not very successful. My current code is :
import os,subprocess
path = "/Users/armed/Desktop/"
for file in os.listdir(path)
command = ['mv', '*.pdf' , 'test.pdf'] // mv Command to rename files to test.pdf
subprocess.call(command)
The output i get for this code is 1 and the files are not renamed. The same command works when executed in the terminal. I am using a Mac (if that helps in any way)
The same command works when executed in the terminal.
Except it's not the same command. The code is running:
'mv' '*.pdf' 'test.pdf'
but when you type it out it runs:
'mv' *.pdf 'test.pdf'
The difference is that the shell globs the * wildcard before executing mv. You can simulate what it does by using the glob module.
Python is not going to expand the shell wildcard in the string by default. You can also do this without a subprocess. But your code will lose all pdf files except the last one.
from glob import glob
import os
path = "/Users/armed/Desktop/"
os.chdir(path)
for filename in glob("*.pdf"):
os.rename(filename, "test.pdf")
But I'm sure that's not what you really want. You'll need a better destination name.