Python ile kırık sembolik bul

oy
16

Ben ararsam os.stat()kırık üzerinde symlink, piton bir atar OSErroristisna. Bu onları bulmak için yararlı bir hale getirir. Ancak, birkaç başka nedeni vardır os.stat()benzer bir istisna olabilir. Kırık saptanmasına daha kesin bir yolu var mı symlinksLinux altında Python ile?

Oluştur 21/08/2008 saat 20:00
kaynak kullanıcı
Diğer dillerde...                            


7 cevaplar

oy
3

Python olmadan sabit bağlantılarını için test bahseder misiniz? / Bin / test dosyaları bir dosya düğümü paylaşırken doğrudur DOSYA1 -ef DOSYA2 koşulu vardır.

Bu nedenle, böyle bir şey find . -type f -exec test \{} -ef /path/to/file \; -printbelirli bir dosyaya sabit bağlantı testi için işler.

Okuma getiriyor hangi man testve bahsettikleri -Lve -hbir dosya üzerinde hangi hem iş hem de o dosya hedef eksikse söylemek etmediği konusunda, bir sembolik bağ ise doğrudur dönün.

Bunu buldunuz head -0 FILE1çıkış kodu dönecekti 0dosya açıldı ve edilebilirse 1düzenli dosyaya bir sembolik bağlantı durumunda hedef okunabilir olmasından bağımsız bir test olarak çalıştığı, olamaz eğer.

Cevap 21/08/2008 saat 20:13
kaynak kullanıcı

oy
1

Bir piton adam değilim ama os.readlink benziyor ()? Ben perl'de kullanmak mantık hedef ve () hedef olup olmadığını görmek için test etmek kullanımı, stat bulmak için readlink () kullanmaktır.

Düzenleme: readlink tanıtıyor bazı Perl dışarı çarptım. Ben perl stat ve readlink ve Python en os.stat () ve os.readlink () sistem çağrıları için her iki sargı olan inanıyoruz, bu nedenle bu iyi kanıtı olabilecek kod olarak makul çevirmek gerekir:

wembley 0 /home/jj33/swap > cat p
my $f = shift;

while (my $l = readlink($f)) {
  print "$f -> $l\n";
  $f = $l;
}

if (!-e $f) {
  print "$f doesn't exist\n";
}
wembley 0 /home/jj33/swap > ls -l | grep ^l
lrwxrwxrwx    1 jj33  users          17 Aug 21 14:30 link -> non-existant-file
lrwxrwxrwx    1 root     users          31 Oct 10  2007 mm -> ../systems/mm/20071009-rewrite//
lrwxrwxrwx    1 jj33  users           2 Aug 21 14:34 mmm -> mm/
wembley 0 /home/jj33/swap > perl p mm
mm -> ../systems/mm/20071009-rewrite/
wembley 0 /home/jj33/swap > perl p mmm
mmm -> mm
mm -> ../systems/mm/20071009-rewrite/
wembley 0 /home/jj33/swap > perl p link
link -> non-existant-file
non-existant-file doesn't exist
wembley 0 /home/jj33/swap >
Cevap 21/08/2008 saat 20:14
kaynak kullanıcı

oy
11

os.lstat () yararlı olabilir. Lstat () başarılı ve stat () başarısız olursa, o zaman muhtemelen kırık bir bağlantı.

Cevap 21/08/2008 saat 20:15
kaynak kullanıcı

oy
2

os.path

Daha sonra bu dosya kullanılarak geçerli bir dosya olup olmadığını belirlemeye çalışıyor, ne sembolik link puan almak realpath () kullanarak deneyebilirsiniz.

(Şu anda bu deneme fırsatı değilim, bu yüzden onunla oynamak ve ne olsun görmek gerekir)

Cevap 21/08/2008 saat 20:19
kaynak kullanıcı

oy
20

Ortak bir Python deyişi o izni daha af sormak daha kolay olmasıdır. Gerçek hayatta bu ifadenin bir hayranı değilim rağmen, vakaların bir çok geçerlidir. Genellikle kodunuzda senin iki çağrı arasında dosyaya ne olacağını asla bilemezsiniz çünkü iki sistem, aynı dosya üzerinde çağıran zincirleri kod önlemek istiyorum.

Tipik bir hata gibi bir şey yazmaktır :

if os.path.exists(path):
    os.unlink(path)

İkinci arama (os.unlink) başka bir şey sizin eğer testten sonra sildiyseniz, başarısız bir özel durum yükseltmek ve yürütme adresinin fonksiyonun geri kalan kısmını durdurabilir. (Bu gerçek hayatta olmaz düşünebilir, ama biz sadece bizim kod temeli geçen hafta dışına Bunun gibi başka hata avlanır - ve onların kafasını kaşıyıp için 'Heisenbug' iddia eden bir kaç programcıları sol böcek nazikti son birkaç ay)

Yani, özel durumda, muhtemelen yapacağını:

try:
    os.stat(path)
except OSError, e:
    if e.errno == errno.ENOENT:
        print 'path %s does not exist or is a broken symlink' % path
    else:
        raise e

Burada sıkıntı, stat sadece orada değil bir sembolik bağ ve kırık bir sembolik bağ için aynı hata kodu döndürür olmasıdır.

Yani, sen atomicity kırmaya daha seçeneğimiz yok sanırım, ve böyle bir şey yapmak

if not os.path.exists(os.readlink(path)):
    print 'path %s is a broken symlink' % path
Cevap 25/08/2008 saat 22:32
kaynak kullanıcı

oy
8

Bu atomik değil ama işe yarıyor.

os.path.islink(filename) and not os.path.exists(filename)

Nitekim tarafından KKO gördüğümüz (fantastik kılavuzu okuma)

os.path.exists (yol)

yolu varolan yolun işaret ederse Gerçek dönün. kırık sembolik bağlantılar için yanlış döndürür.

Ayrıca diyor ki:

izni istendi dosya üzerinde () os.stat yürütmek için verilmediği takdirde Bazı platformlarda bu fonksiyon yolu fiziksel olarak var olsa bile, yanlış döndürebilir.

Eğer izinleri hakkında endişeleriniz varsa Yani, diğer maddeleri eklemek gerekir.

Cevap 28/06/2015 saat 16:49
kaynak kullanıcı

oy
0

bazı ana dir meydana bile nasıl kırık sembolik yakalamak için: Ben benzer bir sorun vardı? Ben de (dosya oldukça büyük bir sayı ile uğraşan bir uygulamada) hepsini oturum istedi ama çok fazla tekrarlar olmadan.

İşte ünite testleri dahil ile geldi budur.

fileutil.py :

import os
from functools import lru_cache
import logging

logger = logging.getLogger(__name__)

@lru_cache(maxsize=2000)
def check_broken_link(filename):
    """
    Check for broken symlinks, either at the file level, or in the
    hierarchy of parent dirs.
    If it finds a broken link, an ERROR message is logged.
    The function is cached, so that the same error messages are not repeated.

    Args:
        filename: file to check

    Returns:
        True if the file (or one of its parents) is a broken symlink.
        False otherwise (i.e. either it exists or not, but no element
        on its path is a broken link).

    """
    if os.path.isfile(filename) or os.path.isdir(filename):
        return False
    if os.path.islink(filename):
        # there is a symlink, but it is dead (pointing nowhere)
        link = os.readlink(filename)
        logger.error('broken symlink: {} -> {}'.format(filename, link))
        return True
    # ok, we have either:
    #   1. a filename that simply doesn't exist (but the containing dir
           does exist), or
    #   2. a broken link in some parent dir
    parent = os.path.dirname(filename)
    if parent == filename:
        # reached root
        return False
    return check_broken_link(parent)

Birim testler:

import logging
import shutil
import tempfile
import os

import unittest
from ..util import fileutil


class TestFile(unittest.TestCase):

    def _mkdir(self, path, create=True):
        d = os.path.join(self.test_dir, path)
        if create:
            os.makedirs(d, exist_ok=True)
        return d

    def _mkfile(self, path, create=True):
        f = os.path.join(self.test_dir, path)
        if create:
            d = os.path.dirname(f)
            os.makedirs(d, exist_ok=True)
            with open(f, mode='w') as fp:
                fp.write('hello')
        return f

    def _mklink(self, target, path):
        f = os.path.join(self.test_dir, path)
        d = os.path.dirname(f)
        os.makedirs(d, exist_ok=True)
        os.symlink(target, f)
        return f

    def setUp(self):
        # reset the lru_cache of check_broken_link
        fileutil.check_broken_link.cache_clear()

        # create a temporary directory for our tests
        self.test_dir = tempfile.mkdtemp()

        # create a small tree of dirs, files, and symlinks
        self._mkfile('a/b/c/foo.txt')
        self._mklink('b', 'a/x')
        self._mklink('b/c/foo.txt', 'a/f')
        self._mklink('../..', 'a/b/c/y')
        self._mklink('not_exist.txt', 'a/b/c/bad_link.txt')
        bad_path = self._mkfile('a/XXX/c/foo.txt', create=False)
        self._mklink(bad_path, 'a/b/c/bad_path.txt')
        self._mklink('not_a_dir', 'a/bad_dir')

    def tearDown(self):
        # Remove the directory after the test
        shutil.rmtree(self.test_dir)

    def catch_check_broken_link(self, expected_errors, expected_result, path):
        filename = self._mkfile(path, create=False)
        with self.assertLogs(level='ERROR') as cm:
            result = fileutil.check_broken_link(filename)
            logging.critical('nothing')  # trick: emit one extra message, so the with assertLogs block doesn't fail
        error_logs = [r for r in cm.records if r.levelname is 'ERROR']
        actual_errors = len(error_logs)
        self.assertEqual(expected_result, result, msg=path)
        self.assertEqual(expected_errors, actual_errors, msg=path)

    def test_check_broken_link_exists(self):
        self.catch_check_broken_link(0, False, 'a/b/c/foo.txt')
        self.catch_check_broken_link(0, False, 'a/x/c/foo.txt')
        self.catch_check_broken_link(0, False, 'a/f')
        self.catch_check_broken_link(0, False, 'a/b/c/y/b/c/y/b/c/foo.txt')

    def test_check_broken_link_notfound(self):
        self.catch_check_broken_link(0, False, 'a/b/c/not_found.txt')

    def test_check_broken_link_badlink(self):
        self.catch_check_broken_link(1, True, 'a/b/c/bad_link.txt')
        self.catch_check_broken_link(0, True, 'a/b/c/bad_link.txt')

    def test_check_broken_link_badpath(self):
        self.catch_check_broken_link(1, True, 'a/b/c/bad_path.txt')
        self.catch_check_broken_link(0, True, 'a/b/c/bad_path.txt')

    def test_check_broken_link_badparent(self):
        self.catch_check_broken_link(1, True, 'a/bad_dir/c/foo.txt')
        self.catch_check_broken_link(0, True, 'a/bad_dir/c/foo.txt')
        # bad link, but shouldn't log a new error:
        self.catch_check_broken_link(0, True, 'a/bad_dir/c')
        # bad link, but shouldn't log a new error:
        self.catch_check_broken_link(0, True, 'a/bad_dir')

if __name__ == '__main__':
    unittest.main()
Cevap 27/10/2016 saat 01:49
kaynak kullanıcı

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more