Reading a file from directory - python

I am trying to read a file in the directory ./resources/input_file.utf8.
However, when I compile the following code from the terminal with the command:
python namefile.py input
this error appears:
[Errno 2] No such file or directory: 'input'
This is my code:
from argparse import ArgumentParser
def parse_args():
parser = ArgumentParser()
parser.add_argument("input_path", help="./resources/input_file.utf8")
return parser.parse_args()
def foo(input_path):
file_input = open(input_path, "r", encoding='utf-8-sig')
for line in file_input:
[...]
if __name__ == '__main__':
args = parse_args()
predict(args.input_path)
One of the specification I have to respect is to not to put hard paths directly in the foo function, but only in the parser.add_argument() function.
How can I fix it?

If you are running the command python namefile.py input, make sure that:
1) Files - You have both your input file and the python script in the same folder.
2) Location - The working directory in you terminal is the one that contains the files (use pwd to check).
3) File name - Your filename is exactly input and not input.txt or input.utf8.
If your file is in the path that you have provided in your example, then you would need to call the script with that path.
Example:
python namefile.py "./resources/input_file.utf8"

Related

How to set directory in python script

When I run my python script via the terminal by going into the directory the python script is held and running > python toolstation.py, the script runs successfully.
Then what I try to do is run the script via a .bat file. My .bat file is set as so:
"C:\Users\xxxx\AppData\Local\Programs\Python\Python39\python.exe" "C:\Users\xxxx\Downloads\axp_solutions\python_scripts\toolstation.py"
When I run this bat file, it gives me an exception which states it cannot find the directory to open the csv file, which is one directory above the python script.
Exception:
Traceback (most recent call last):
File "C:\Users\xxx\Downloads\axp_solutions\python_scripts\toolstation.py", line 12, in <module>
f = open('../input/toolstation.csv', 'r')
FileNotFoundError: [Errno 2] No such file or directory: '../input/toolstation.csv'
The code for this in the python script is set like so:
f = open('../input/toolstation.csv', 'r')
Now I can set this via a hardcoded path like so to get around it:
f = open('C:/Users/xxxx/Downloads/axp_solutions/input/toolstation.csv', 'r')
But as I am sending this script and bat file to a friend, they will have a different path set. So my question is, how should the dynamic path be set so that it is able to recognise the directory to go to?
Instead of constructing the path to the CSV file (based on this answer), I would suggest using Python's argparse library to add an optional argument which takes the path to that CSV file.
You could give it a reasonable default value (or even use the automatically determined relative path as the default), so that you don't have to specify anything if you are on your system, while at the same time adding a lot of flexibility to your script.
You and everyone using your script, can at any moment decide which CSV file to use, while the overhead is manageable.
Here's what I would start with:
import argparse
import os
DEFAULT_PATH = r'C:\path\that\makes\sense\here\toolstation.csv'
# Alternatively, automatically determine default path:
# DEFAULT_PATH = os.path.join(
# os.path.dirname(os.path.abspath(__file__)),
# r'..\input\toolstation.csv',
# )
parser = argparse.ArgumentParser(prog='toolstation')
parser.add_argument(
'-i',
'--input-file',
default=DEFAULT_PATH,
help='Path to input CSV file for this script (default: %(default)s).'
)
args = parser.parse_args()
try:
in_file = open(args.input_file, 'r')
except FileNotFoundError:
raise SystemExit(
f"Input file '{args.input_file}' not found. "
"Please provide a valid input file and retry. "
"Exiting..."
)
Your script gets a nice and extensible interface with out-of-the-box help (you can just run python toolstation.py --help).
People using your script will love you because you provided them with the option to choose their input file via:
python toolstation.py --input-file <some_path>
The input file path passed to the script can be absolute or relative to the directory the script is executed from.
Use os module to get the script path and then add the path to the src file.
Ex:
import os
path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'input', 'toolstation.csv')
with open(path, 'r') as infile:
...
You can pass the path to that CSV in as an argument to the python script.
This tutorial may be helpful.
The batch file:
set CSV_PATH="C:\...\toolstation.csv"
"C:\...\python.exe" "C:\...\toolstation.py" %CSV_PATH%
You'll have to fill in the "..."s with the appropriate paths; this isn't magic.
The Python script:
import sys
toolstation_csv = sys.argv[1]
...
f = open(toolstation_csv, 'r')
...

Python unable to find file in folder tree

I'm getting an error when I try to load one of the configuration files. Here is the folder structure:
script.rb
root_folder
command_line_interface.py
extras
utils.py
AZ
config1.txt
config2.txt
BZ
config1.txt
config2.txt
The query folows: script.rb > command_line_interface.py > utils.py > config2.txt
In script.rb:
IO.popen("./root_folder/command_line_interface.py -arg1 5")
In command_line_interface.py:
if __name__ == '__main__':
sys.path.append(os.path.dirname(sys.argv[0]))
parser = argparse.ArgumentParser(description='Test')
parser.add_argument('-arg1', '--arg1', action='store', type=int, help='Test', dest='arg1')
args = parser.parse_args()
if args.arg1:
utils.run(action)
In utils.py dinamically load config.txt according to action parameter using base_path:
def run(action):
base_path = 'extras/BZ/'
.
.
.
filename = base_path + 'config2.txt'
with open(filename) as f:
result = json.load(f)
IOError: [Errno 2] No such file or directory: '\extras\BZ\config2.txt'
It works when called directly in windows prompt inside root_folder, but it does't when called from script.rb. It needs to run on both cases.
Does anyone knows what is causing the error?
your ruby script isn't started inside the root_folder, so your relative base path isn't correct. You can use os.getcwd() to fetch your current working directory. A relative path always starts from there.
In general it is better to always use absolute paths, when possible. For creating absolute pathes, it is good practice to use os.path.join() instead of just concatenating strings.
Remember that if your run script.rb from its folder then ALL OF THE CODE gets run as if it were in that folder.
And so I think you should try setting base_path to './root_folder/extras/BZ/' just to check if that's the problem.
The solution was:
def run(action):
base_path = os.path.join(os.path.dirname(sys.argv[0]), 'extras/BZ/')

Error when creating directory and then opening a file within it in Python, but no error if directory already exists

I expect a directory to be created and then a file to be opened within it for writing to when I execute my code below in Python 2.6.6,
import subprocess
def create_output_dir(work_dir):
output_dir = '/work/m/maxwell9/some_name5/'
subprocess.Popen(['mkdir', output_dir])
return output_dir
if __name__ == '__main__':
work_dir = '/work/m/maxwell9/'
output_dir = create_output_dir(work_dir)
#output_dir = '/work/m/maxwell9/some_name5/'
filename = output_dir + 'bt.sh'
with open(filename, 'w') as script:
print('there')
but instead I get the error,
Traceback (most recent call last):
File "slurm_test.py", line 13, in <module>
with open(filename, 'w') as script:
IOError: [Errno 2] No such file or directory: '/work/m/maxwell9/some_name5/bt.sh'
If I run the script, I can then see that the directory is created. If I then uncomment the line,
#output_dir = '/work/m/maxwell9/some_name5/'
and comment the line,
output_dir = create_output_dir(work_dir)
then the file is output fine. So there is something about creating the folder and then writing to it in the same script that is causing an error.
subprocess.Popen starts up an external process but doesn't wait for it to complete unless you tell it to (e.g. by calling .wait on the returned Popen instance). Most likely, mkdir is in the process of creating a directory while open(filename, 'w') attempts to create a file in that directory. This is an example of a "race condition".
The solution is to .wait on the open process (as noted above), or you can use one of the convenience wrappers subprocess.check_output, subprocess.check_call or (even better), you can avoid subprocess entirely by using os.mkdir or os.makedirs.
You could use the os library instead of subprocess, which makes for a more straightforward implementation. Try swapping out your create_output_dir function with this:
import os
def create_output_dir(work_dir):
try:
os.makedirs(work_dir)
except OSError:
pass
return work_dir

Getting file path from command line arguments in python

I would like to read a file path from command line arguments, using argparse. Is there any optimal way to check if the path is relative (file is in current directory) or the complete path is given? (Other than checking the input and adding current directory to file name if the path does not exist.)
As Display Name said, os.path.isabs along with sys.argv is probably the best:
import sys
import os
fpath = sys.argv[-1]
print(os.path.isabs(fpath))
print(fpath)
output
>>>
True
C:\Users\310176421\Desktop\Python\print.py
>>>
some cmd stuff
C:\Users\310176421\Desktop\Python>python print.py C:\Users\310176421\Desktop\tes
t.txt
True
C:\Users\310176421\Desktop\test.txt
C:\Users\310176421\Desktop\Python>python print.py whatever
False
whatever

Opening a file in pwdir's folder in Python through Applescript

Opening a file available in present working directory's temp folder in python
I tried
pwdir=os.getcwd()
tempdir=pwdir+"/temp/test.txt"
f=open(tempdir,'r+')
When I print the path of tempdir, it is showing up correctly and also the contents of file are also read.
When I try to combine this operation from an Applescript, which calls this python script. I get an error like this
f=open(pwdir1,'r+')
IOError: [Errno 2] No such file or directory: '//temp/test.txt'" number 1
EDIT:
I am using Shell script from Applescript to call this pythonscript
do shell script "/Users/mymac/Documents/'Microsoft User Data'/test.py"
EDIT:
Python Code:
tempdir = os.path.join(os.getcwd(),'temp','htmlinput.html')
print tempdir
with open(tempdir) as f:
html=f.read()
Python output from terminal:(works perfectly fine)
/Users/mymac/Documents/Microsoft User Data/Outlook Script Menu Items/temp/htmlinput.html
I am also able to see the file contents.
Applescript Code:
do shell script "/Users/mymac/Documents/'Microsoft User Data'/'Outlook Script Menu Items'/new.py"
Applescript Error:
error "Microsoft Outlook got an error: Traceback (most recent call last):
File \"/Users/mymac/Documents/Microsoft User Data/Outlook Script Menu Items/new.py\", line 12, in <module>
with open(tempdir) as f:
IOError: [Errno 2] No such file or directory: '/temp/htmlinput.html'" number 1
I don't know Applescript -- or OS X in general. It looks like the script is being run from the root folder, and os.getcwd() returns '/'. The directory of the script itself is sys.path[0] or the dirname of the current module -- dirname(__file__) -- if it's a single script instead of a package. Try one of the following
import os, sys
tempdir = os.path.join(sys.path[0], 'temp', 'temp.txt')
or
import os
tempdir = os.path.join(os.path.dirname(__file__), 'temp', 'temp.txt')
The double slash is your problem. The right way to join file and path names in Python is with os.path.join. Try:
tempdir = os.path.join(os.getcwd(), 'temp', 'test.txt')
Also, you should probably be doing:
with open(tempdir) as f:
which will make sure tempdir gets closed even if you have an error.
Edit:
We need to see what tempdir is when the script is invoked by the AppleScript, not when it is invoked from the terminal. If you do
tempdir = os.path.join(os.getcwd(),'temp','htmlinput.html')
with open('/Users/mymac/Documents/temp.txt', 'w') as fwrite:
fwrite.write(tempdir)
What exactly ends up in the file /Users/mymac/Documents/temp.txt?

Categories

Resources