Don't understand the why configparser can't find the config file - python

I'm using cofigparser in my python project. Directory structure is as following:
root/dir/data.py
root/dir/config.ini
data.py code:
config_parser = configparser.RawConfigParser()
config_file_path = "data/config.ini"
config_parser.read_file(open(config_file_path))
This works from local machine. But when Im trying to build it from Jenkins, output is:
> config_parser.read_file(open(config_file_path)) 19:09:04
> FileNotFoundError: [Errno 2] No such file or directory:
> 'data/config.ini'
After many attempts to resolve it I find out, that from Jenkins it works only if I include root to the path, so as I change it as following:
config_file_path = "root/data/config.ini"
It starts working on Jenkins. But - I have above error message on local machine now. So now Im in the situation, that if I can run my code from local machine, I have to change that path, and don`t forget to change it back, when Im commiting changes to git. Has anybody any idea, why is that? And how to write the path which will work on both?
Note1:
All the imports Im using in project are without root directory included, so for example:
from dir.dir2 import foo
If I include root dir, it never works from Jenkins.
Note2:
Both machines running Windows.

Related

Run Python Script From Script Directory/Current Directory

[Introduction]
Hi! I'm working on a python script to automate installation of UWP-Apps, it's been a long time i'm not touching Python; until this day. The script uses Depedencies inside the script directory, i've looking up on my older scripts and found this specific code.
os.chdir(os.path.dirname(sys.argv[0]))
[Problematic]
However, using the above code doesn't work on my current script but it's working fine on older scripts. When using above, it shows:
OSError: [WinError 123] The filename, directory name, or volume label syntax is incorrect: ''
Already looking up on Internet about this topic; but most of them was talking about running the script from outer/different directory that leads me to dead end.
Any helps is appreciated :)
The easiest answer is probably to change your working directory, then call the .py file from where it is:
cd path/to/python/file && python ../.py
Of course you might find it even easier to write a script that does it all for you, like so:
Save this as runPython.sh in the directory where you're running the python script from, is:
#!/bin/sh
cd path/to/python/file
python ../script.py
Make it executable (for yourself):
chmod +x ./runPython.sh
Then you can simply enter your directory and run it:
./runPython.sh
If you want to only make changes to the python script:
mydir = os.getcwd() # would be the folder where you're running the file
mydir_tmp = "path/to/python/file" # get the path
mydir_new = os.chdir(mydir_tmp) # change the current working directory
mydir = os.getcwd()
The reason you got an error was because sys.argv[0] is the name of the file itself, instead you can pass the directory as a string and use sys.argv[1] instead.
import os
from os.path import abspath, dirname
os.chdir(dirname(abspath(__file__)))
You can use dirname(abspath(__file__))) to get the parent directory of the python script and os.chdir into it to make the script run in the directory where it is located.

'No such file or directory' error when using nosetests

I have a little Python project of which I recently made a Conda package. Making the package was a pain on its own, however, I recently started adding tests to this using nosetests, which made it even harder.
To introduce: my package takes a certain input, performs a lot of (quantum chemical) calculations and then generates a folder in the same directory as the script which calls the package, containing the output data (some .png files, .txt files and binary files)
Using nosetests, I would like to check whether these output files are how they should be. I created a Python test script (using unittest) which creates the input and calls my package. Next, it imports the created file and the test file. However, this is where it goes wrong. I get the error that this file does not exist:
FileNotFoundError: [Errno 2] No such file or directory: 'results\\output.txt'
The directory looks like this:
project-path\
- tests\
- test-script.py
- results\
- output.txt
I call nose by running this in Anaconda prompt:
project-path> nosetests tests
And I import the file in the Python test script using:
result_file = open('results\\output.txt', 'r').read()
Does anyone know what goes wrong here? I think it has to do with the fact that the tests are executed in a test environment. In that case: how do I import my files?
Get the absolute path to output.txt, it is indeed the most reliable way to locate and open it.
import os, sys
basedir = os.path.dirname(sys.argv[0])
filename = "output.txt"
path = os.path.join(basedir, "results", filename)
result_file = open(path, 'r').read()

Call a file in another folder in Eclipse for Python project

I have a small enough Python project in Eclipse Neon and keep getting the same error and can't find proper documentation on how to solve. In my main I need to call a file that is located in another folder. The error I receive is IOError: [Errno 2] No such file or directory:
I have an empty init.py file in the folder (XML_TXT) that I'm trying to use.
It looks like Groovy is importing okay, or else you would get an ImportError. An IOError indicates that it can't find "test.txt". Does that file exist?
It will work if the file path is relative to where you are running the script from. So for example if test.txt is in a folder
Groovy("folder_name/test.txt")
You can also go up in the directory structure if you need to, for example
Groovy("../folder_name/test.txt")
Or, if you want to be able to run the file from anywhere, you can have python work out the absolute path of the file for you.
import os
filename = os.path.join(os.path.dirname(__file__), 'folder_name/test.txt')
u = Groovy(filename)

IOError: [Errno 2] No such file or directory: 'users.txt'

I am getting the above error when I use a webserver to run my code, however locally in the Terminal this works fine. I believe this must be to do with the path to the file working locally but not remotely. I have seen the solution on stackoverflow is to add the filepath like '/user/xxx/library/' etc, however is there a solution that allows this to be system agnostic? As in if I copy this directory to another location/server it will still work?
You can import os, it's built it to Python. You can get teh absolute path of the .py file this way:
import os
ROOT = lambda base : os.path.join(os.path.dirname(__file__), base).replace('\\','/')
Now you can simply do the following:
ROOT('users.txt')
It should return the absolute path.

Crontab Python Script Execution (Can't find settings config file)

My Crontab -l
# m h dom mon dow command
SHELL=/bin/bash
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
00 8,20 * * * python /home/tomi/amaer/controller.py >>/tmp/out.txt 2>&1
My controller.py has config file settings.cfg also it uses other script in the folder it's located (I chmoded only controller.py)
The error
1;31mIOError^[[0m: [Errno 2] No such file or directory: 'settings.cfg'
I have no idea how to fix this? Please help me?
Edit: The part that read the config file
def main():
config=ConfigParser.ConfigParser()
config.readfp(open("settings.cfg"),"r")
As I initially wrote in my comment, this is because you are using relative path to the current working directory. However, that is not going to be the same when running all this via the cron executable rather than the python interpreter directly via the shebang.
Your current code would look for the "settings.cfg" in the current working directory which is where the cron executable resides, and not your script. Hence, you would need to change your code logic to using absolute paths by the help of the "os" built-in standard module.
Try to following line:
import os
...
def main():
config = ConfigParser.ConfigParser()
scriptDirectory = os.path.dirname(os.path.realpath(__file__))
settingsFilePath = os.path.join(scriptDirectory, "settings.cfg")
config.readfp(open(settingsFilePath,"r"))
This will get your the path of your script and then appends the "settings.cfg" with the appropriate dir separator for your operating system which is Linux in this particular case.
If the location of the config file changes any time in the future, you could use the argparse module for processing a command line argument to handle the config location properly, or even without it simply just using the first argument after the script name like sys.argv[1].
Your code is looking for settings.cfg in its current working directory.
This working directory will not be the same when cron executes the job, hence the error
You have two "easy" solutions:
Use an absolute path to the config file in your script (/home/tomi/amaer/config.cfg)
CD to the appropriate directory first in your crontab (cd /home/tomi/amaer/ && python /home/tomi/amaer/controller.py)
The "right" solution, though, would be to pass your script a parameter (or environment variable) that tells it where to look for the config file.
It's not exactly good practice to assume your config file will always be lying just next to your script.
You might want to have alook at this question: https://unix.stackexchange.com/questions/38951/what-is-the-working-directory-when-cron-executes-a-job

Categories