I noticed the following gem in python's source code for ntpath..
def islink(path):
"""Test for symbolic link.
On WindowsNT/95 and OS/2 always returns false
"""
return False
This obviosly isn't the case for vista beyond. So, whenever python encounters a windows symbolic link, it always says that it isn't. To make things more interesting,
x = os.stat(symbolic_link_name)
x.st_mode
16895
import stat
stat.S_ISLNK(x.st_mode)
False
Which means stat it's self does not record the ordinals/flags which indicate that the file is a symbolic link. I would like to fix this or at least point this out to developers, but for the life of me, I can't find the source code for where os.stat() is being compiled from.
Where do I go to edit this source code?
Related
I'm trying to figure the root cause of an issue in a single-threaded Python program that essentially goes like this (heavily simplified):
# Before running
os.remove(path)
# While running
if os.path.isfile(path):
with open(path) as fd:
...
I'm essentially seeing erratic behavior where isfile (which uses stat, itself using GetFileAttributesExA under the hood in Python 2.7, see here) can return True when the file doesn't exist, failing the next open call.
path being on an SMB3 network share, I'm suspecting caching behavior of some kind. Is it possible that GetFileAttributesExA returns stale information?
Reducing SMB client caching from the default (10s) to 0s seems to make the issue disappear:
Set-SmbClientConfiguration -DirectoryCacheLifetime 0 -FileInfoCacheLifetime 0
(Note: The correct fix here is to try opening the file and catch the exception, of course, but I'm puzzled by the issue and would like to understand the root cause.)
I need to develop a plugin for GIMP and would like to stay with PyCharm for Python editing, etc.
FYI, I'm on Windows.
After directing PyCharm to use the Python interpreter included with GIMP:
I also added a path to gimpfu.py to get rid of the error on from gimpfu import *:
This fixes the error on the import, even when set to Excluded.
I experimented with setting this directory to Sources, Resources and Excluded and still get errors for constants such as RGBA-IMAGE, TRANSPARENT_FILL, NORMAL_MODE, etc.
Any idea on how to contort PyCharm into playing nice for GIMP plugin development?
Not really running any code from PyCharm, it's really just being used as a nice code editor, facilitate revisions control, etc.
As you find this variables are part of .pyd files (dll files for Python). PyCharm can't get signatures for content of this files.
For Python builtins (like abs, all, any, etc.) PyCharm has it's own .py files that uses only for signatures and docs. You can see it if you'll click on some of this funcs and go to it's declaration:
PyCharm will open builtins.py file in it's folder with following content:
def abs(*args, **kwargs): # real signature unknown
""" Return the absolute value of the argument. """
pass
def all(*args, **kwargs): # real signature unknown
"""
Return True if bool(x) is True for all values x in the iterable.
If the iterable is empty, return True.
"""
pass
def any(*args, **kwargs): # real signature unknown
"""
Return True if bool(x) is True for any x in the iterable.
If the iterable is empty, return False.
"""
pass
As you see functions are defined and documented, but have no implementation, because their implementation created with C and placed somewhere in binary file.
Pycharm can't provide such wrapper for every library. Usually people who created .pyd files provide their .py wrappers (for example, PyQt module: no native python implementation, just signatures).
Looks like Gimp doesn't have such wrapper for some of variables. Only way I see is to create some sort of own wrapper manually. For example, create gimpfu_signatures.py with following content:
RGBA_IMAGE = 1
TRANSPARENT_FILL = 2
NORMAL_MODE = 3
And import it while you're creating plugin:
from gimpfu import *
from gimpfu_signatures import * # comment on release
Not elegant, but better then nothing.
...
One more note about gimpfu.py's path. If I understand correctly, you just added this path to project. It may work, but correct way is to add it to project's PYTHONPATH (in project preferences). See this link for detailed manual.
On Windows 7 with Python 2.7 how can I detect if a path is a symbolic link?
This does not work os.path.islink(), it says it returns false if false or not supported and the path I'm providing is definitely a symbolic link so I'm assuming it's not supported on windows? What can I do?
The root problem is that you're using too old a version of Python. If you want to stick to 2.x, you will not be able to take advantage of new features added after early 2010.
One of those features is handling NTFS symlinks. That functionality was added in 3.2 in late 2010. (See the 3.2, 3.1, and 2.7 source for details.)
The reason Python didn't handle NTFS symlinks before then is that there was no such thing until late 2009. (IIRC, support was included in the 6.0 kernel, but userland support requires a service pack on Vista/2008; only 7/2008R2 and newer come with it built in. Plus, you need a new-enough MSVCRT to be able to access that userland support, and Python has an explicit policy of not upgrading to new Visual Studio versions within a minor release.)
The reason the code wasn't ported back to 2.x is that there will never be a 2.8, and bug fix releases like 2.7.3 (or 2.7.4) don't get new features, only bug fixes.
This has been reported as issue 13143, and the intended fix is to change the 2.7 docs to clarify that islink always returns False on Windows.
So, if you want to read NTFS symlinks under Windows, either upgrade to Python 3.2+, or you have to use win32api, ctypes, etc. to do it yourself.
Or, as Martijn Pieters suggests, instead of doing it yourself, use a third-party library like jaraco.windows that does it and/or borrow their code.
Or, if you really want, borrow the code from the 3.2 source and build a C extension module around it. If you trace down from ntpath to os to nt (which is actually posixmodule.c), I believe the guts of it are in win32_xstat_impl and win32_xstat_impl_w.
This is what I ended up using to determine if a file or a directory is a link in Windows 7:
from subprocess import check_output, CalledProcessError
import os.path
import ctypes
def isLink(path):
if os.path.exists(path):
if os.path.isdir(path):
FILE_ATTRIBUTE_REPARSE_POINT = 0x0400
attributes = ctypes.windll.kernel32.GetFileAttributesW(unicode(path))
return (attributes & FILE_ATTRIBUTE_REPARSE_POINT) > 0
else:
command = ['dir', path]
try:
with open(os.devnull, 'w') as NULL_FILE:
o0 = check_output(command, stderr=NULL_FILE, shell=True)
except CalledProcessError as e:
print e.output
return False
o1 = [s.strip() for s in o0.split('\n')]
if len(o1) < 6:
return False
else:
return 'SYMLINK' in o1[5]
else:
return False
EDIT: Modified code as per suggestions of Zitrax and Annan
EDIT: Added include statements as per the suggestion of shioko
For directories:
import os, ctypes
def IsSymlink(path):
FILE_ATTRIBUTE_REPARSE_POINT = 0x0400
return os.path.isdir(path) and (ctypes.windll.kernel32.GetFileAttributesW(unicode(path)) & FILE_ATTRIBUTE_REPARSE_POINT):
Source
You can also use the pywin32 module: GetFileAttributes is available in the win32api sub-module and FILE_ATTRIBUTE_REPARSE_POINT in the win32con module. For instance, to test if a given path is a symlink to a directory, the code becomes:
import os
import win32api
import win32con
def is_directory_symlink(path):
return bool(os.path.isdir(path)
and (win32api.GetFileAttributes(path) &
win32con.FILE_ATTRIBUTE_REPARSE_POINT))
If using Python 2 and the path may contain non-ascii characters, GetFileAttributes requires a unicode string. However, simply using unicode(path) will generally fail: you should test if path is a str and, if so, use its decode method.
Just using if file[-4:len(file)] != ".lnk": works for me
I would like to know if there is a way I could check from my python code if matlab exists on a system. So far the only thing I can come up with is: exists = os.system("matlab") and then parse the exists for a command not found. But I'm almost sure this will:
Start matlab in case it exists on the system. I don't want this.
The response may vary depending on the system I'm running ?
So is there any way I could check if a matlab installation is available on the system from python ?
Regards,
Bogdan
Assuming your system call works, you can check the path for matlab.exe like this:
import os
def matlab_installed():
for path in os.environ["PATH"].split(";"):
if os.path.isfile(os.path.join(path, "matlab.exe")):
return True
return False
For Unix, you have to change split(";") to split(":") and "matlab.exe" to whatever the matlab executable is called under Unix.
Another way would be to to use shutil
import shutil
mt = shutil.which("matlab")
If 'matlab' is found it returns the path where it was found, else it returns 'NoneType'. You may check for 'matlab' or 'matlab.exe' depending on the OS.
I'm trying to get the list of meta-data associated to a file, using python in Ubuntu.
Without using python, the command "extract" works very well but I don't know how to use it with python, I always get a message saying that "extract" is not defined.
I assume you're asking about the metadata that appears in the Windows "Properties" dialogue under the "Summary" tab. (If not, just disregard this.) Here's how I managed it.
Download and install Python win32 extensions. This will put win32, win32com, etc. into your Python[ver]/Lib/site-packages folder. These bring the win32api, win32com, etc. For some reason, I couldn't get the version for Python 2.6 (in build 216) to work. I updated my system to Python 2.7 and used the 216 build for Python 2.7, and it worked. (To download & install, follow the link above, click the link reading 'pywin32', click the link for the latest build (currently 216), click the link for the .exe file that matches your system and Python installation (for me, it was pywin32-216.win32-py2.7.exe). Run the .exe file.)
Copy and paste the code from the "Get document summary information" page on Tim Golden's tutorial into a .py file on your own computer.
Tweak the code. You don't really have to tweak the code, but if you run this Tim's script as your main module, and if you don't supply a pathname as your first sys.argv, then you'll get an error. To make the tweak, scroll down to the bottom of the code, and omit the final block, which starts with if __name__ == '__main__':.
Save your file as something like property_reader.py, and call its property_sets(filepath) method. This method returns a generator object. You can iterate through the generator to see all the properties and their values. You could implement it like this:
# Assuming 'property_reader.py' is the name of the module/file in which you saved Tim Golden's code...
import property_reader
propgenerator = property_reader.property_sets('[your file path]')
for name, properties in propgenerator:
print name
for k, v in properties.items ():
print " ", k, "=>", v
The output of the above code will be something like the following:
DocSummaryInformation
PIDDSI_CATEGORY => qux
SummaryInformation
PIDSI_TITLE => foo
PIDSI_COMMENTS => flam
PIDSI_AUTHOR => baz
PIDSI_KEYWORDS => flim
PIDSI_SUBJECT => bar
extract is based on the libextractor library. You can access the library from Python by installing the python-extractor package on Ubuntu.
In case you're using Windows your question has been addressed on SO already.