Windows üzerinde Python os.path.join


100

Python öğrenmeye çalışıyorum ve bir komut dosyası çıkaracak bir program yapıyorum. Os.path.join'i kullanmak istiyorum ama kafam oldukça karışık. Dokümanlara göre dersem:

os.path.join('c:', 'sourcedir')

Anlıyorum "C:sourcedir". Dokümanlara göre bu normal, değil mi?

Ancak copytree komutunu kullandığımda, Python bunu istediğim şekilde çıkaracak, örneğin:

import shutil
src = os.path.join('c:', 'src')
dst = os.path.join('c:', 'dst')
shutil.copytree(src, dst)

İşte aldığım hata kodu:

WindowsError: [Hata 3] Sistem belirtilen yolu bulamıyor: 'C: src /*.*'

Ben sarmak Eğer os.path.joinile os.path.normpathI aynı hatayı alıyorum.

Bu takdirde os.path.joinbu şekilde kullanılamaz, o zaman amacına olarak karıştı.

Stack Overflow tarafından önerilen sayfalara göre, birleştirmede eğik çizgiler kullanılmamalıdır - bu doğru mu?

Yanıtlar:


60

Windows, her sürücü için geçerli dizin konseptine sahiptir. Bu nedenle "c:sourcedir", geçerli C: dizini içinde "sourcedir" anlamına gelir ve mutlak bir dizin belirtmeniz gerekir.

Bunlardan herhangi biri çalışmalı ve aynı sonucu vermeli, ancak şu anda iki kez kontrol etmem için çalıştırılan bir Windows VM yok:

"c:/sourcedir"
os.path.join("/", "c:", "sourcedir")
os.path.join("c:/", "sourcedir")

8
os.path.join ('C: /', 'sourcedir') beklendiği gibi çalıştı. Çok teşekkür ederim efendim :) diğerleri '//' 'c:' 'c: \\' çalışmadı (C: \\ iki ters eğik çizgi oluşturdu, C: \ hiç çalışmadı) Tekrar teşekkürler ghostdog74 , Smashery ve Roger Pate. Size borçluyum :)
Frank E.

Maalesef satır sonları yorumda tutulmadı, çok dağınık görünüyor
Frank E.

Bu bazı durumlarda işe yarasa bile, @AndreasT'ın cevabı çok daha iyi bir çözümdür. Os.sep'i kullanmak, işletim sistemine bağlı olarak / ve \ arasında seçim yapacaktır.
SenhorLucas

Kullanmanın bir anlamı var mı os.path.joinveya yine de os.sepbelirtecekseniz c:? c:diğer işletim sistemlerinde hiçbir anlam ifade etmiyor.
naught101

tüm bu çözümler yalnızca kısmen tatmin edicidir. Tek bir özel durumunuz olduğunda ayırıcıyı manuel olarak eklemekte sorun yoktur, ancak bunu programlı olarak yapmak istemeniz durumunda, hangisinden os.path.join('c:','folder')farklı çalışan kriterler os.path.join('folder','file')nelerdir? Bunun nedeni yüzünden mi :yoksa nedeniyle 'c: `Bir diski?
Vincenzooo

126

Daha da bilgiçlikçi olmak için, python belgelerine ilişkin en tutarlı cevap şu olacaktır:

mypath = os.path.join('c:', os.sep, 'sourcedir')

Posix kök yolu için de os.sep'e ihtiyacınız olduğundan:

mypath = os.path.join(os.sep, 'usr', 'lib')

5
Cehaletimi bağışlayın - Görünüşe göre kod hala Windows ve Linux arasında değişiyor, bu yüzden os.sepüstün olan nedir?
pianoJames

3
Enjekte etmeye çalışırken lütfen bu sorunu not edin os.sep. Yalnızca çıplak sürücü harfinden sonra çalışır. >>> os.path.join ("C: \ goodbye", os.sep, "temp") 'C: \\ temp'
Jobu

1
@pianoJames cevabım, sistemden bağımsız bir çözüm sağlamak için bundan yola çıkıyor: stackoverflow.com/a/51276165/3996580
Scott Gigante

Tüm bu "bilgiçlikçi" çözümlerin amacını anlamıyorum. os.sepayırıcı hakkında varsayımlar yapmadan yolları değiştirmek istediğinizde kullanışlıdır. os.path.join()Doğru ayırıcıyı zaten bildiği için kullanmak anlamsız . Ayrıca, kök dizini adıyla açıkça belirtmeniz gerekirse de anlamsızdır (kendi örneğinizde görebileceğiniz gibi). Neden "c:" + os.sepyerine basitçe "c:\\"veya os.sep + "usr"yerine basitçe "/usr"? Ayrıca, Win mermilerinde cd c:yapamayacağınızı cd c:\ , ancak yapabileceğinizi , kök adının aslında olduğunu öne sürdüğünü unutmayın c:\ .
Michael Ekoka

13

Nedeni os.path.join('C:', 'src')beklediğiniz gibi çalışmıyor, bağladığınız belgelerdeki bir şeyden kaynaklanıyor:

Windows'ta, her sürücü için geçerli bir dizin olduğundan, os.path.join ("c:", "foo"), C sürücüsündeki geçerli dizine göre bir yolu temsil eder: (c: foo), c değil : \ foo.

Ghostdog'un dediği gibi, muhtemelen mypath=os.path.join('c:\\', 'sourcedir')


12

Bilgiçlik taslamak için, yol ayırıcı olarak ya / ya da \ kodunun gömülmesi muhtemelen iyi değildir. Belki bu en iyisi olur?

mypath = os.path.join('c:%s' % os.sep, 'sourcedir')

veya

mypath = os.path.join('c:' + os.sep, 'sourcedir')

12

Giriş yolu ne olursa olsun, hem Windows hem de Linux üzerinde çalışan sistemden bağımsız bir çözüm için, os.path.join(os.sep, rootdir + os.sep, targetdir)

Windows'ta:

>>> os.path.join(os.sep, "C:" + os.sep, "Windows")
'C:\\Windows'

Linux'ta:

>>> os.path.join(os.sep, "usr" + os.sep, "lib")
'/usr/lib'

1
Teşekkürler! Bu, @Jobu'nun daha önce bahsettiği hasardan etkilenmediği için daha da kullanışlıdır: os.path.join (os.sep, "C: \\ a" + os.sep, "b") "C: \\ a \\ b "Windows'ta.
pianoJames

1
Yine de bu örneklerden herhangi biri sistemden bağımsızdır? c:* usr
nix'te

İşlev çağrısı tamos.path.join(os.sep, rootdir + os.sep, targetdir) olarak sistemden bağımsızdır çünkü kodu değiştirmeye gerek kalmadan bu sisteme özgü örneklerin her ikisiyle de çalışır.
Scott Gigante

Bu çözüm, ilham veren önceki yazıya çok benzer şekilde, hala rootdir gibi ayarlamaya dayanıyor rootdir = "usr" if nix else "c:". Ancak daha doğrudan ve doğru rootdir = "/usr" if nix else "c:\\"olan, os.sepakrobasi ve ardından gelen kafa kaşınmaları olmadan da aynı şekilde çalışır . Herhangi bir tehlike * nix bir kök dizin eğik çizgi dışında başka bir şey ile başlayacak veya Windows Win kabuklarda örneğin bir arka kolon ve ters eğik çizgi (olmadan adlı kök dizinleri sahip olacağını, sadece yapamam var cd c:, şimdi etsen sondaki ters eğik çizgiyi belirtmeniz gerekir), öyleyse neden başka türlü davranasınız?
Michael Ekoka

7

Bunun bir (windows) python hatası olduğunu söyleyebilirim.

Neden böcek?

Bence bu ifade True

os.path.join(*os.path.dirname(os.path.abspath(__file__)).split(os.path.sep))==os.path.dirname(os.path.abspath(__file__))

Ama FalseWindows makinelerinde.


1
Bunun bir Python hatası oluşturduğunu kabul etme eğilimindeyim. Hala durum bu mu? ( 2015 sonlarının görkemli ütopik geleceğinden yazılmıştır. )
Cecil Curry

Bir Windows makinesine erişimim olmadığı için bu soruyu pencerelerle ilgili olarak cevaplayamam ama sanırım Python'un bu soruyla ilgili davranışı değişmedi. Her neyse, bu ifade Linux uygulamaları için de doğru değildir, çünkü ilk ifade baştaki ayırıcı olmadan (kök dizin olarak da bilinir) yolu döndürürken, ikinci ifade baştaki ayırıcıyı içeren yolu döndürür.
georg

Bu yüzden aslında bu soruyla ilgili cevabımı artık beğenmiyorum. Ama python'un bu konudaki davranışını da sevmiyorum.
georg

@Cecil Ben de şu anda bu sorunun üzerindeyim çünkü aynı sorun ... hala böyle görünüyor.
joshmcode

5

Windows yoluna katılmak için deneyin

mypath=os.path.join('c:\\', 'sourcedir')

temelde, eğik çizgiden kaçmanız gerekecek


4

Windows'ta yolu en kodlanmış olanlardan (ham dize değişmezleri veya kaçan ters eğik çizgiler kullanarak) en az olanlara kadar işlemek için birkaç olası yaklaşımınız vardır. Beklendiği gibi çalışacak birkaç örnek aşağıda verilmiştir. İhtiyaçlarınıza daha uygun olanı kullanın.

In[1]: from os.path import join, isdir

In[2]: from os import sep

In[3]: isdir(join("c:", "\\", "Users"))
Out[3]: True

In[4]: isdir(join("c:", "/", "Users"))
Out[4]: True

In[5]: isdir(join("c:", sep, "Users"))
Out[5]: True

0

@ Georg- ile onay

O halde neden topal ihtiyacımız olduğunu söyleyebilirim os.path.join- kullanmak daha iyi str.joinveya unicode.joinörneğin

sys.path.append('{0}'.join(os.path.dirname(__file__).split(os.path.sep)[0:-1]).format(os.path.sep))

2
evet, doğru, bu şekilde daha net. Siz varken neden normal ifadeler kullanmıyorsunuz? veya bir perl betiğini çağırıp çıktıyı işlemek mi?
Jean-François Fabre

Bunun iyi bir fikir olduğunu sanmıyorum çünkü os.path.join oldukça iyi anlambilim ... Yani onu bir kodda görüyorsunuz ve neler olduğunu hemen anlıyorsunuz.
SenhorLucas

0

yorumunuzu yanıtlayarak: "diğerleri '//' 'c:', 'c: \\' işe yaramadı (C: \\ iki ters eğik çizgi oluşturdu, C: \ hiç çalışmadı)"

Windows kullanımı , sourcedir'in önüne os.path.join('c:', 'sourcedir') otomatik olarak iki ters eğik çizgi ekler .\\

Piton ileri eğik çizgi ile de pencerelerin üzerinde çalışır gibi yolunu gidermek için -> '/' basitçe ekleyin .replace('\\','/')ile os.path.joinaşağıdaki gibi: -

os.path.join('c:\\', 'sourcedir').replace('\\','/')

Örneğin: os.path.join('c:\\', 'temp').replace('\\','/')

çıktı: 'C: / temp'


0

Önerilen çözümler ilginçtir ve iyi bir referans sunar, ancak sadece kısmen tatmin edicidir. Tek bir özel durumunuz olduğunda veya giriş dizesinin formatını biliyorsanız, ayırıcıyı manuel olarak eklemekte sorun yoktur, ancak bunu genel girişlerde programlı olarak yapmak istediğiniz durumlar olabilir.

Biraz deney yaparak, birinci segment bir sürücü harfiyse, yani tek bir harf ve ardından iki nokta üst üste, gerçek bir birime karşılık gelse bile, yol sınırlayıcının eklenmemesi kriterine inanıyorum.

Örneğin:

import os
testval = ['c:','c:\\','d:','j:','jr:','data:']

for t in testval:
    print ('test value: ',t,', join to "folder"',os.path.join(t,'folder'))
test value:  c: , join to "folder" c:folder
test value:  c:\ , join to "folder" c:\folder
test value:  d: , join to "folder" d:folder
test value:  j: , join to "folder" j:folder
test value:  jr: , join to "folder" jr:\folder
test value:  data: , join to "folder" data:\folder

Kriterleri test etmenin ve bir yol düzeltmesi uygulamanın uygun bir yolu os.path.splitdrive, ilk döndürülen öğeyi test değeriyle karşılaştırmak olabilir t+os.path.sep if os.path.splitdrive(t)[0]==t else t.

Ölçek:

for t in testval:
    corrected = t+os.path.sep if os.path.splitdrive(t)[0]==t else t
    print ('original: %s\tcorrected: %s'%(t,corrected),' join corrected->',os.path.join(corrected,'folder'))
original: c:    corrected: c:\  join corrected-> c:\folder
original: c:\   corrected: c:\  join corrected-> c:\folder
original: d:    corrected: d:\  join corrected-> d:\folder
original: j:    corrected: j:\  join corrected-> j:\folder
original: jr:   corrected: jr:  join corrected-> jr:\folder
original: data: corrected: data:  join corrected-> data:\folder

Muhtemelen takip eden boşluklar için daha sağlam olacak şekilde geliştirilebilir ve bunu sadece pencerelerde test ettim, ancak umarım bir fikir verir. Ayrıca bkz. Os.path: bu davranışı açıklayabilir misiniz? pencereler dışındaki sistemlerle ilgili ilginç ayrıntılar için.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.