Path.replace(target) does not work with my approach - python

Pathlib is suggested instead of os.module because is newer. However I find less documentation about Pathlib if I look for. I show an issue that give me problems.
Initial condition
In a directory I have the following files:
I want to change the prefix of the files "comune_min_corr_" in "zp".
OS approach
With the following code where df4 is dataframe that contain "comune":
for comune in df4:
os.replace('./Spedire/comune_min_corr_'+str(comune)+'.gpkg', './Spedire/zp_'+str(comune)+'.gpkg')
To be clear, "comune" in the following image are three items: Airolo, Alto Malcantone, Aranno. They are part of the filename.
The result is right, the files "zp_comune.gpkg" are replaced by the files "comune_min_corr_comune.gpkg" and "comune_min_corr_comune.gpkg" disappear:
Pathlib approach
I create again the "initial condition".
Then, I try to do the same thing than before, adapting for the "pathlib.replace(target)".
They say here https://realpython.com/python-pathlib/ that we have to use "source.replace(destination)" structure. I did with the following code.
for comune in df4:
Path=('Spedire')
('/comune_min_corr_'+str(comune)+'.gpkg').replace('/comune_min_corr_'+str(comune)+'.gpkg','/zp_'+str(comune)+'.gpkg')
It give me no error but it does not work, the content of the directory does not change
Question
Could you provide the solution to obtain the same result for pathlib that I obtain with os? Please explain your step and why it does not work for pathlib.
Thank you.

#Barmar I changed now and it works. Thank you
To resume:
with os.replace() it work without defining a variable because replace() is a function of the module "os".
with "path.replace" we have to do so:
for comune in df4:
variable = Path('Spedire')/f'comune_min_corr_{comune}.gpkg'
variable.replace(Path('Spedire')/f'zp_{comune}.gpkg')
In fact, we have to build an object (here called "variable") because "path.replace" is a class of the module "pathlib". Class always needs to have an object to obtain something because otherwise python does not know what we are talking about.
To be noted: I probably have done something similar, but I repeateadly worked confusing "gpkg" with "gpgk". This trivial mistake leads me in the wrong way.
If I told something wrong, please correct me.

Related

Easiest way to append non-directory component to Python Path?

Several SO questions ask how to append a directory to a pathlib.Path object. That's not this question.
I would like to use a Path object a prefix for a series of files in a single directory, like this:
2022-01-candidates.csv
2022-01-resumes.zip
2022-02-candidates.csv
2022-02-resumes.zip
Ideally, I would construct Path objects for the 2022-01 and 2022-02 components, and then append -candidates.csv and -resumes.zip to each.
Unfortunately, Path appears to only understand appending subdirectores, not extensions to existing path names.
The only workaround that I see is something like p.parent / (p.name + "-candidates.csv"). Although that's not so bad, it's clumsy and this pattern is common for me. I wonder whether I'm missing a more streamlined method. (For example, why isn't there a + concatenation operator?)
Path.with_suffix() requires that the suffix start with a dot, so that doesn't work.
As you mentioned, using the division operator always creates a sub-directory, and with_suffix is only for extensions. You could use with_path to edit the filename:
import pathlib
path = pathlib.Path("2022-01")
path.with_name(f"{path.name}-candidates.csv")

Renaming files with different Names depending upon different match cases in Python

I'm a newbie at python, I'm trying to write a python code to rename multiple files with different names depending upon different match cases, here's my code
for i, file in enumerate(os.listdir(inputpath)):
if(match(".*"716262_2.*$"),file):
dstgco="Test1"+"DateHere"+".xls"
gnupgCommandOp=gnupgCommand(os.rename(os.path.join(inputpath,file),os.path.join(inputpath,dstgco)))
returnCode = call(gnupgCommandop)
if(match(".*"270811_2.*$"),file):
dstgmo="Test2"+"DateHere"+".xls"
gnupgCommandOp=gnupgCommand(os.rename(os.path.join(inputpath,file),os.path.join(inputpath,dstgmo)))
returnCode = call(gnupgCommandop)
currently what is happening is only one file is getting renamed which is Test2 DateHere with str object is not a callable error, my requirement is to rename files present at the location depending on the different match cases, I'm writing incorrect for loop or if statements?
things I have tried :
used incremental count
used glob
used only os.listdir and not enumerate
seems like it is matching the first statement and breaking on the next retrieval, may be I wrote If statements wrong
I can't debug this since I'm calling this code from an internal tool using a bat file.
can someone please help me out with this, I know only a single gnupgCommandOp should be used, is my syntax is wrong? is what would be a better way to achieve this?

Alteryx MD5_ASCII() function equivalent solution in Python

I'm not able to match the results of an MD5_ASCII() function in my Python program. Unfortunately I can't post the exact input string and results so please bear with me.
My code in Python looks something like this:
import hashlib
str_text = "SV6*123*TT"
str_hashed_1 = hashlib.md5(str_text.encode()).hexidigest()
The produced string does not match the MD5_ASCII() output. What is the correct way of doing this?
I've eventually found the issue. There was nothing wrong with the hashing function, the issue was with the input itself.

Getting just the current directory without the full path in python

I apologize if this is a question that has already been resolved. I want to get the current directory when running a Python script or within Python. The following will return the full path including the current directory:
os.getcwd()
I can also get the path all the way up to the current directory:
os.path.dirname(os.getcwd())
Using os.path.split will return the same thing as the above, plus the current folder, but then I end up with an object I want:
(thing_I_dont_want, thing_I_want) = os.path.split(os.getcwd())
Is there a way I can get just the thing I want, the current folder, without creating any objects I don't want around? Alternately, is there something I can put in place of the variable thing_I_dont_wantthat will prevent it from being created (e.g. (*, thing_I_want))?
Thanks!
Like this:
os.path.split(os.getcwd())[1]
Although os.path.split returns a tuple, you don't need to unpack it. You can simply select the item that you need and ignore the one that you don't need.
Use os.path.split:
>>> os.path.split(os.getcwd())
('/home/user', 'py')
>>> os.path.split(os.getcwd())[-1]
'py'
help on os.path.split:
>>> print os.path.split.__doc__
Split a pathname. Returns tuple "(head, tail)" where "tail" is
everything after the final slash. Either part may be empty.
You could try this, though it's not safe (as all the given solutions) if the pathname ends with a / for some reason:
os.path.basename(os.getcwd())
The standard pythonic way of denoting that "this is a thing I don't want" is to call it _ - as in:
_, thing_I_want = os.path.split(os.getcwd())
Note that this doesn't do anything special. The object is being created inside os.split(), and it's still being returned and given the name _ - but this does make it clear to people reading your code that you don't care about that particular element.
As well as being a signal to other people, most IDEs and code validators will understand that the variable called _ is to be ignored, and they won't do things like warn you about it never being used.

Referencing long names with Python Sphinx

I'm working on documentation for my Python module (using Sphinx and reST), and I'm finding that when cross-referencing other Python objects (modules, classes, functions, etc) the full object name ends up being incredibly long. Often it is longer than 80 characters, which I would like to avoid at all costs.
Here is an example:
def exampleFunction():
'''Here is an example docstring referencing another
:class:`module1.module2.module3.module4.module5.ReallyLongExampleClassName`
'''
The issue is that when creating the documentation for the ReallyLongExampleClassName class, I generated it for the full path name module1.module2.module3.module4.module5.ReallyLongExampleClassaName.
I'm wondering if there is any way to solve this? I have tried the following methods, with no success:
1) Adding a line break in the middle of the module name. Example:
:class:`module1.module2.module3.module4.
module5.ReallyLongExampleClassName`
2) Referencing the class name in a different (but still Python importable) way. Example:
:class:`module1.module2.ReallyLongClassName`
I believe that since the documentation for ReallyLongClassName is tied to the full path names that Sphinx cannot correlate the shortened version with the fully named version.
Edit 04/05/2012:
As per the answer/suggestion of j13r (see below) I tried the following:
:class:`module1.module2.module3.module4.module5\
ReallyLongExampleClassName`
And this worked successfully. The only caveat to get this to work, is that the second line must not have spaces before it (which is quite frustrating when using this in a docstring). Thus to make my original example work it would look like:
def exampleFunction():
'''Here is an example docstring referencing another
:class:`module1.module2.module3.module4.module5.\
ReallyLongExampleClassName`
'''
Nice, and ugly. If you were to put spaces before ReallyLongExampleClassName to indent it to the same level as the line above it the output would include the spaces and thus Sphinx would try to reference something like module1.module2.module3.module4.module5.ReallyLongExampleClassName.
I should also note that I tried two other variations of this, which did NOT work:
# Note: Trying to put a space before the '\'
:class:`module1.module2.module3.module4.module5. \
ReallyLongExampleClassName`
# Note: Trying to leave out the '\'
:class:`module1.module2.module3.module4.module5.
ReallyLongExampleClassName`
I was looking for a solution that didn't involve destroying the formatting of the docstring, but I suppose it will do...I think I actually prefer a line that goes past 80 characters to this.
Thanks to j13r for the answer!
According to the sphinx documentation (https://www.sphinx-doc.org/en/master/usage/restructuredtext/domains.html#cross-referencing-python-objects) you could use a dot before your target class:
:class:`.ReallyLongExampleClassName`
or
:class:`.module5.ReallyLongExampleClassName`
and let sphinx search for the class:
... if the name is prefixed with a dot, and no exact match is found, the target is taken as a suffix and all object names with that suffix are searched. For example, :py:meth:.TarFile.close references the tarfile.TarFile.close() function, even if the current module is not tarfile. Since this can get ambiguous, if there is more than one possible match, you will get a warning from Sphinx.
You can use ~ as prefix, it does exactly what you want.
http://sphinx-doc.org/markup/inline.html#xref-syntax
Another strategy is to use reST Substitutions. This will let you save more space in the text by calling the :class: cross-reference later on:
def exampleFunction():
'''Here is an example docstring referencing another
|ReallyLongExampleClassName|
.. |ReallyLongExampleClassName| replace::
:class:`.ReallyLongExampleClassName`
'''
If you're referring to the same class in many of your files, you could instead put the substitution in your Sphinx conf.py file, using the rst_epilog setting. From the Sphinx documentation:
rst_epilog
A string of reStructuredText that will be included at the end of every source file that is read. This is the right place to add substitutions that should be available in every file. An example:
rst_epilog = """
.. |psf| replace:: Python Software Foundation
"""
New in version 0.6.
Then your docstring would just be:
def exampleFunction():
'''Here is an example docstring referencing another
|ReallyLongExampleClassName|
'''
Wild stab in the dark. Perhaps this works:
:class:`module1.module2.module3.module4.\
module5.ReallyLongExampleClassName`
It would be valid Python
import scipy.\
stats

Categories

Resources