Python relpath /home/<username> vs. ~ - python

In Python3.4 (and also 2.6), using the os.path.relpath cmd, I get different answers if I run:
os.path.relpath("~/foo/bar.txt", "~")
than if I run
os.path.relpath("~/foo/bar.txt", "/home/<username>/")
(where I replace <username> with my user name, naturally!)
Namely, if I'm in my home directory, in the first case I get
foo/bar.txt
(as I would expect), but in the second case I get
~/foo/bar.txt
which is not what I would expect, given that ~ is exactly /home/<username>. (I get the same result in the second case regardless of whether I include the trailing '/' in the second arg.)
The second case gives an even more bizarre result if I run this within a subdirectory of my home directory, say ~/Data/:
Data/~/foo/bar.txt
which unless I'm mistaken is a non-existent directory.
I can figure out a work-around for this, but what is the logic for why it's happening this way? I don't suppose it's a bug, since it's been around a long time.

~ isn’t actually always your home directory—that’s only your shell’s interpretation. You can create a directory named ~ anywhere you want, just as you could create a directory named orange. Since ~ could be a plain old directory name, Python is treating it that way.
If you want Python to interpret ~ as meaning the home directory, as a shell would do, you need to tell Python you want to replace ~ with the path to the home directory using os.path.expanduser before passing your directory names to relpath.

Related

Why os.path.realpath doesn't work properly

i just downloaded a file called "N_PR_8705_004A_.doc" in my "Downloads" folder and i want to put it into my "Stage NLP" folder using os. I know how to do it without os but i'd like that shit to work it's faster and it simply doesnt. First i tried to get the path of my file doing this:
import os
os.path.dirname(os.path.abspath("N_PR_8705_004A_.doc"))
# or os.path.realpath it's the same
and the result i get is:
'C:\\Users\\f002722\\Stage NLP'
whereas when i do list all the files in this folder doing:
os.listdir("C:\\Users\\f002722\\Stage NLP")
you clearly see it is simply not there:
['.ipynb_checkpoints',
'ADR service study - D2 (1st part).pdf',
'basetal.py',
'Codes test',
'Cours NLP.ipynb',
'e Deorbit',
'edot CDF study.pdf',
'edot_v5.pdf',
'Entrainement.ipynb',
'ESA edot workshop May 6th 2014 - Summary.msg',
'ESA_edotWorkshop-_Envisat_attitude-Copy1',
'ESA_edotWorkshop-_Envisat_attitude.pdf',
'ESA_edotWorkshop_GNC_.pdf',
'ESA_INNOCENTI_Challenges.pdf',
'ESA_Robin_Biesbroek_edot.pdf',
'GMV_edot_Symposium.pdf',
'JOP_edotWorkshop.pdf',
'KT_HAARMANN_Edot.pdf',
'MDA_edot_Symposium_-_Robotic_Capture.pdf',
'MDA_eDot_Symposium_-_Robotic_Capture.pdf.kx2zd5w.partial',
'Note_Ariane_NLP.ipynb',
'Note_Ariane_NLP_2.ipynb',
'Note_Ariane_NLP_3.ipynb',
'OHB_eDotWorkshop_ADRM.pdf',
'OHB_Sweden_eDotWorkshop_PRISMA_and_IRIDES.pdf',
'SKA_Polska_eDotWorkshop_Net_Simulator.pdf',
'TAS_Carole_Billot_edot.pdf',
'Test.ipynb',
'Text_clustering_v3_2.py',
'Webinar_OOSandADR_7May2020.pdf',
'__pycache__']
So what the hell is going on i'm out of ideas here.
Thx in advance
I think I have a possible answer to your question. Neither realpath nor abspath require their arguments to name existing files. In particular, the documentation for abspath() says: "On most platforms, this is equivalent to calling the function normpath() as follows: normpath(join(os.getcwd(), path))."
This means that if you have a Python script that has a line like,
foo = os.path.dirname(os.path.abspath("doesnotexist"))
then the value of foo will be the current working directory of the script. Since "doesnotexist" isn't the name of a file in this directory, it won't show up if you do os.listdir(foo).
I notice that you wrote that "N_PR_8705_004A_.doc" was in your "Downloads" directory, which is obviously not the same as 'C:\\Users\\f002722\\Stage NLP'. If 'C:\\Users\\f002722\\Stage NLP' is the working directory for your Python script, then running os.path.dirname(os.path.abspath("N_PR_8705_004A_.doc")) is just like writing os.path.dirname(os.path.abspath("doesnotexist")), for the reasons that I just gave.
Python can't automatically figure out the path of a file just by giving it a relative file name. For example, there could be many files named README.txt on a system, each in different directories, so there's no way for os.path.abspath('README.txt') to know which of those directories you want.
To move the file "N_PR_8705_004A_.doc" from the "Downloads" directory to 'C:\\Users\\f002722\\Stage NLP', you'd probably need to do something like this:
import shutil
shutil.move('C:\\Users\\f002722\\Downloads\\N_PR_8705_004A_.doc',
'C:\\Users\\f002722\\Stage NLP')
presuming, of course, that the "Downloads" directory was inside 'C:\\Users\\f002722'.

FTP giving 550 error when using ftp.cwd() twice

When I run this part:
directory = ftp.pwd()
file_name = 'config.single'
ftp.cwd('plugins/GAListener')
print('dir:', directory)
ftp.cwd('plugins/CrateReloaded/crates')
It says:
ftplib.error_perm: 550 No such file or directory.
When I change the directory several times inside an if statement, it works fine.
Are you unable to change the working directory like that? Do I need to reset to the main server directory prior to changing to another? If so, how would I do that?
Whichever directory comes first in the code is the one it goes to, then gives an error upon trying to change to the second. With the second ftp.cwd() commented out, the first one runs without problem, no matter which directory it points to, so they're definitely both there.
Additionally, when I print directory, it just prints / and not plugins/GAListener.
Edit: When doing this inside an if statement, all the directories go where they're supposed to and I'm given no errors without a leading slash.
if day_of_week == 0 and file_name not in ftp.nlst():
ftp.rename('config.yml', 'config.single')
ftp.rename('config.double', 'config.yml')
print('plugins/GAListener/config.yml is now plugins/GAListener/config.single.')
print('plugins/GAListener/config.double is now plugins/GAListener/config.yml.')
ftp.cwd('plugins/MOTDCountdown')
ftp.rename('config.yml', 'config.sunday')
ftp.rename('config.monday', 'config.yml')
print('plugins/MOTDCountdown/config.yml is now plugins/MOTDCountdown/config.sunday.')
print('plugins/MOTDCountdown/config.monday is now plugins/MOTDCountdown/config.yml.')
ftp.cwd('plugins/Essentials')
ftp.rename('motd.txt', 'motd.sunday')
ftp.rename('motd.monday', 'motd.txt')
After the first cwd you end up in folder:
/plugins/GAListener
Changing to a relative path plugins/CrateReloaded/crates (without a leading slash) will resolve it against the current working directory. So it will attempt to open folder:
/plugins/GAListener/plugins/CrateReloaded/crates
Which most probably does not exist.
I assume you want to go to
/plugins/CrateReloaded/crates
For that you have to use an absolute path (with a leading slash):
ftp.cwd('/plugins/CrateReloaded/crates')

diff output of two python programs in windows cmd

So I am trying to compare output of two python programs, which have files that I will call trace1.py and trace2.py. Currently I am using process substitution with diff to try and compare their outputs, however I'm having trouble with finding both files, since they are in separate sub-directories of my current directory:
diff <(python /subdir1/tracing1.py) <(python /subdir2/tracing2.py)
When I run this, I get
The system cannot find the file specified.
I think I'm messing up some sort of path formatting, or else I'm using the process substitution incorrectly.
EDIT: In the end I decided that I didn't need to use process substitution, and instead could just diff program output after each program is run. However thanks to Fallenreaper in the comments, I was able to find a single command that does what I initially wanted:
python subdir1/tracing1.py > outfile1.txt & python subdir2/tracing2.py > outfile2.txt & diff outfile1.txt outfile2.txt
Sorry, not enough rep to comment yet :(
Your line works perfectly when you remove that slash. I would suggest using absolute path names or a relative path from current directory cos that front slash would take you to your root directory.
Cheers.

What directory does os.path.join start at?

I made a script in the past to mass rename any file greater than x characters in a directory. When I made that script I had a source directory which you would need to input manually. Any file that was over x characters in that directory would be stripped of it's extension, renamed, then the extension would be re added and it would use os.path.join to join the source and the newly created filename+ext. I'm now making another script and used os.path.join("Folder in the current dir", "file in that dir"). Because this worked I'm guessing that when os.path.join is called with just a foldername and no full path in it's first parameter it starts it's search from the directory that the script it was run in? Just wondering if this is correct.
os.path.join has nothing to do with any actual filesystem, and does not "start" anywhere. It simply joins two arbitrary paths, whether they exist or not.
What os.path.join does is to just join path elements the system-compatible way, taking into effect the particular directory separator character, etc., into account. It's a simple string manipulation tool.
So the returned result simply starts from whatever you give to it as the first argument.

Python os module path functions

From the documentation:
os.path.realpath(path)
Return the canonical path of the specified filename, eliminating any
symbolic links encountered in the path (if they are supported by the
operating system).
When I invoke this with an extant file's name, I get the path to it: /home/myhome/myproject.
When I invoke this with a 'nonsense.xxx' string argument, I still get a path to /home/myhome/myproject/nonsense.xxx. This is a little inconsistent because it looks like nonsense.xxx is taken to be a directory not a file (though it is neither: it does not exist).
When I invoke this with a null string file name, I still get a path to /home/myhome/myproject.
How can I account for this behaviour when the documentation says so little about realpath()? (I am using Python 2.5.)
Edit: Somebody suggested a way to test if files exist. My concern is not to test if files exist. My concern is to account for behaviour.
os.path isn't interested in whether or not the files exist. It is merely concerned with constructing paths.
realpath eliminates known symlinks from the equation, but directories that do not exist are assumed to be valid elements of a path regardless.
Rather than guess, just read the code! It's there in your python installation. Or browse here, it's only 14 lines minus comments.
Place test such as "os.path.isfile(x)", "x is not None" and "os.path.isdir(x)" before the call?

Categories

Resources