How to delete a file without an extension? - python

I have made a function for deleting files:
def deleteFile(deleteFile):
if os.path.isfile(deleteFile):
os.remove(deleteFile)
However, when passing a FIFO-filename (without file-extension), this is not accepted by the os-module.
Specifically I have a subprocess create a FIFO-file named 'Testpipe'.
When calling:
os.path.isfile('Testpipe')
It results to False. The file is not in use/open or anything like that. Python runs under Linux.
How can you correctly delete a file like that?

isfile checks for regular file.
You could workaround it like this by checking if it exists but not a directory or a symlink:
def deleteFile(filename):
if os.path.exists(filename) and not os.path.isdir(filename) and not os.path.islink(filename):
os.remove(filename)

Related

Remove file in python with absolute path: error "no such file or directory" but file exists

I'm trying to remove a file in Python 3 on Linux (RHEL) the following way:
os.remove(or.getcwd() + '/file.txt')
(sorry not allowed to publish the real paths).
and it gives me the usual error
No such file or directory: '/path/to/file/file.txt'
(I've respected slash or antislash in the path)
What is strange is that when I just ls the file (by copy pasting, so the very same path) the file does exist.
I've read this post but i'm not on Windows and slash direction seems correct.
Any idea ?
EDIT: as suggested by #DominicPrice os.system('ls') is showing the file while os.listdir() does not show it (but shows other files in the same directory)
EDIT 2: So my issue was due a a bad usage of os.popen. I used this method to copy file but did not wait for the subprocess to be terminated. So my understanding is that the file was not copied yet when I tried to delete it.
The problem is that, as you have explained in the comments, you are creating the file using os.popen("cp ..."). This works asynchronously, so it may not have had time to complete by the time you call os.remove(). You can force python to wait for it to finish by calling the close method:
proc = os.popen("cp myfile myotherfile")
proc.close() # wait for process to finish
os.remove("myotherfile") # we're all good
I would highly recommend staying away from using os.popen in favour of the subprocess library, which has a run function which is way safer to use.
For the specific functions of copying a file, an even better (and cross platform) solution is to use the shutil library:
import shutil
shutil.copyfile("myfile", "myotherfile")
you should use os.path.dirname(__file__).
this is an inbuilt function of os module in python.
you can read more here.
https://www.geeksforgeeks.org/find-path-to-the-given-file-using-python/

How can I reproducibly (py)test the failure mode of code that opens a file if the file is missing?

I would like to write a pytest case for the behavior of a function that opens a file in case that file does not exist.
I think the question boils down to a different one, namely "How can I be sure a file path does not exist on the file system?"
import pytest
def file_content(file_name):
with open(file_name, "r") as f:
return f.read()
def test_file_content_file_not_found():
file_name_of_inexistent_file = "???"
with pytest.raises(FileNotFoundError):
file_content(file_name_of_inexistent_file)
test_file_content_file_not_found()
"???" denotes the spot I think some great tool out there implements a reasonable and secure way to generate a file name or a mock file system that ensures the failure is guaranteed, but also doesn't need to change the file system.
At the moment, I have a small helper function that generates random strings that are tested if they are existing files and if they are not are returned. This way I can emulate the desired behavior. However, I guess there must be a more standard way to achieve this.
the easiest way is to use the builtin tmp_path fixture to generate a unique, empty directory:
def test_does_not_exist(tmp_path):
with pytest.raises(FileNotFoundError):
file_content(tmp_path.joinpath('dne'))
tmp_path is generated per-test and will start empty, so dne will never exist
if you want a generic, non-pytest solution you can use tempfile.TemporaryDirectory directly:
with tempfile.TemporaryDirectory() as tmpdir:
with pytest.raises(FileNotFoundError):
file_content(os.path.join(tmpdir, 'dne'))
disclaimer: I'm a pytest core dev

Methods to avoid hard-coding file paths in Python

Working with scientific data, specifically climate data, I am constantly hard-coding paths to data directories in my Python code. Even if I were to write the most extensible code in the world, the hard-coded file paths prevent it from ever being truly portable. I also feel like having information about the file system of your machine coded in your programs could be security issue.
What solutions are out there for handling the configuration of paths in Python to avoid having to code them out explicitly?
One of the solution rely on using configuration files.
You can store all your path in a json file like so :
{
"base_path" : "/home/bob/base_folder",
"low_temp_area_path" : "/home/bob/base/folder/low_temp"
}
and then in your python code, you could just do :
import json
with open("conf.json") as json_conf :
CONF = json.load(json_conf)
and then you can use your path (or any configuration variable you like) like so :
print "The base path is {}".format(CONF["base_path"])
First off its always good practise to add a main function to go with each class to test that class or functions in the file. Along with this you determine the current working directory. This becomes incredibly important when running python from a cron job or from a directory that is not the current working directory. No JSON files or environment variables are then needed and you will obtain interoperation across Mac, RHEL and Debian distributions.
This is how you do it, and it will work on windows also if you use '\' instead of '/' (if that is even necessary, in your case).
if "__main__" == __name__:
workingDirectory = os.path.realpath(sys.argv[0])
As you can see when you run your command, the working directory is calculated if you provide a full path or relative path, meaning it will work in a cron job automatically.
After that if you want to work with data that is stored in the current directory use:
fileName = os.path.join( workingDirectory, './sub-folder-of-current-directory/filename.csv' )
fp = open( fileName,'r')
or in the case of the above working directory (parallel to your project directory):
fileName = os.path.join( workingDirectory, '../folder-at-same-level-as-my-project/filename.csv' )
fp = open( fileName,'r')
I believe there are many ways around this, but here is what I would do:
Create a JSON config file with all the paths I need defined.
For even more portability, I'd have a default path where I look for this config file but also have a command line input to change it.
In my opinion passing arguments from command line would be best solution. You should take a look at argparse . This allows you to create nice way to handle arguments from the command line. for example:
myDataScript.py /home/userName/datasource1/

Python temporary directory to execute other processes?

I have a string of Java source code in Python that I want to compile, execute, and collect the output (stdout and stderr). Unfortunately, as far as I can tell, javac and java require real files, so I have to create a temporary directory.
What is the best way to do this? The tempfile module seems to be oriented towards creating files and directories that are only visible to the Python process. But in this case, I need Java to be able to see them too. However, I also want the other stuff to be handled intelligently if possible (such as deleting the folder when done or using the appropriate system temp folder)
tempfile.NamedTemporaryFile and tempfile.TemporaryDirectory work perfectly fine for your purposes. The resulting objects have a .name attribute that provides a file system visible name that java/javac can handle just fine, just make sure to:
Set the suffix appropriately if the compiler insists on files being named with a .java extension
Always call .flush() on the file handle before handing the .name of a NamedTemporaryFile to an external process or it may (usually will) see an incomplete file
If you don't want Python cleaning up the files when you close the objects, either pass delete=False to NamedTemporaryFile's constructor, or use the mkstemp and mkdtemp functions (which create the objects, but don't clean them up for you).
So for example, you might do:
# Create temporary directory for source and class files
with tempfile.TemporaryDirectory() as d:
# Write source code
srcpath = os.path.join(d.name, "myclass.java")
with open(srcpath, "w") as srcfile:
srcfile.write('source code goes here')
# Compile source code
subprocess.check_call(['javac', srcpath])
# Run source code
# Been a while since I've java-ed; you don't include .java or .class
# when running, right?
invokename = os.path.splitext(srcpath)[0]
subprocess.check_call(['java', invokename])
... with block for TemporaryDirectory done, temp directory cleaned up ...
tempfile.mkstemp creates a file that is normally visible in the filesystem and returns you the path as well. You should be able to use this to create your input and output files - assuming javac will atomically overwrite the output file if it exists there should be no race condition if other processes on your system don't misbehave.

Python: execfile from other file's working directory?

I have some code that loads a default configuration file and then allows users to supply their own Python files as additional supplemental configuration or overrides of the defaults:
# foo.py
def load(cfg_path=None):
# load default configuration
exec(default_config)
# load user-specific configuration
if cfg_path:
execfile(cfg_path)
There is a problem, though: execfile() executes directives in the file specified by cfg_path as if it were in the working directory of foo.py, not its own working directory. Thus, import directives might fail if the cfg_path file does, say, from m import x where m is a module in the same directory as cfg_path.
How do I execfile() from the working directory of its argument, or otherwise achieve an equivalent result? Also, I've been told that execfile is deprecated in Python 3 and that I should be using exec, so if there's a better way that I should be doing this, I'm all ears.
Note: I don't think solutions which merely change the working directory are correct. That won't put those modules on the interpreter's module-lookup path, as far as I can tell.
os.chdir lets you change the working directory as you wish (you can extract the working directory of cfg_path with os.path.dirname); be sure to first get the current directory with os.getcwd if you want to restore it when you're done exec'ing cfg_path.
Python 3 does indeed remove execfile (in favor of a sequence where you read the file, compile the contents, then exec them), but you need not worry about that, if you're currently coding in Python 2.6, since the 2to3 source to source translation deals with all this smoothly and seamlessly.
Edit: the OP says, in a comment, that execfile launches a separate process and does not respect the current working directory. This is false, and here's an example showing that it is:
import os
def makeascript(where):
f = open(where, 'w')
f.write('import os\nprint "Dir in file:", os.getcwd()\n')
f.close()
def main():
where = '/tmp/bah.py'
makeascript(where)
execfile(where)
os.chdir('/tmp')
execfile(where)
if __name__ == '__main__':
main()
Running this on my machine produces output such as:
Dir in file: /Users/aleax/stko
Dir in file: /private/tmp
clearly showing that execfile does keep using the working directory that's set at the time execfile executes. (If the file executed changes the working directory, that will be reflected after execfile returns -- exactly because everything is taking place in the same process!).
So, whatever problems the OP is still observing are not tied to the current working directory (it's hard to diagnose what they may actually be, without seeing the code and the exact details of the observed problems;-).

Categories

Resources