โมดูล Python os.chmod (ไฟล์ 664) ไม่เปลี่ยนสิทธิ์เป็น rw-rw-r— แต่ -w - wx ----


111

เมื่อเร็ว ๆ นี้ฉันใช้ระบบปฏิบัติการโมดูล Python เมื่อฉันพยายามเปลี่ยนการอนุญาตของไฟล์ฉันไม่ได้รับผลลัพธ์ที่คาดหวัง ตัวอย่างเช่นฉันตั้งใจจะเปลี่ยนสิทธิ์เป็น rw-rw-r--,

os.chmod("/tmp/test_file", 664)

การอนุญาตเป็นเจ้าของจริง -w - wx --- (230)

--w--wx--- 1 ag ag 0 Mar 25 05:45 test_file

อย่างไรก็ตามหากฉันเปลี่ยนรหัส 664 เป็น 0664 ผลลัพธ์ก็คือสิ่งที่ฉันต้องการเช่น

os.chmod("/tmp/test_file", 0664)

ผลลัพธ์คือ:

-rw-rw-r-- 1 ag ag 0 Mar 25 05:55 test_file

ใครช่วยอธิบายได้ไหมว่าเหตุใดการนำ 0 จึงสำคัญมากเพื่อให้ได้ผลลัพธ์ที่ถูกต้อง


33
ฐานแปด ฐานแปด ฐานแปด
Cole Johnson

6
ฉันเปิดปัญหาสำหรับเอกสาร python ที่bugs.python.org/issue25377เพราะควรจะชัดเจนจากเอกสาร
Karl Richter

คำตอบ:


130

พบสิ่งนี้ในฟอรัมอื่น

หากคุณสงสัยว่าทำไมศูนย์นำหน้าจึงมีความสำคัญนั่นเป็นเพราะการอนุญาตถูกตั้งค่าเป็นจำนวนเต็มฐานแปดและ Python จะถือว่าจำนวนเต็มใด ๆ โดยอัตโนมัติโดยให้ศูนย์นำหน้าเป็นฐานแปด ดังนั้น os.chmod ("file", 484) (เป็นทศนิยม) จะให้ผลลัพธ์เดียวกัน

สิ่งที่คุณกำลังทำคือการส่งผ่าน664ซึ่งเป็นเลขฐานแปด1230

ในกรณีของคุณคุณจะต้อง

os.chmod("/tmp/test_file", 436)

[อัปเดต] หมายเหตุสำหรับ Python 3 คุณมีคำนำหน้าด้วย 0o (ศูนย์โอ้) เช่น,0o666


1
ขอบคุณ แต่ฉันยังสับสนว่า 484 ในฐานสิบหมายถึง 744 ในรูปฐานแปดซึ่งเหมาะสมกับหัวข้อที่คุณกล่าวถึงในฟอรัม อย่างไรก็ตามถ้าฉันให้ 644 เป็นทศนิยมมันจะไปที่ 1204 ในรูปฐานแปด 1204 เกี่ยวข้องกับ 230 ในเลขฐานแปดอย่างไร?
AplusG

2
@AplusG คือ1จะไม่ทิ้ง! นั่นคือความเหนียว / setuid / setgid บิตและ 1 stickyหมายถึง การใช้ls -lคุณอาจสังเกตเห็นการอนุญาตในขณะนี้รวมถึงTในตอนท้าย ...
MestreLion

2
ง่ายกว่าที่จะเพิ่ม 0 และทำให้เป็นฐานแปด :)
radtek

10
หมายเหตุสำหรับ Python 3 คุณมีคำนำหน้าด้วย 0o (ศูนย์โอ้)
Mawg กล่าวว่าคืนสถานะ Monica

1
ฉันใช้ 0o ใน python 2.7.10
Wyrmwood

125

ดังนั้นสำหรับผู้ที่ต้องการความหมายคล้ายกับ:

$ chmod 755 somefile

ใช้:

$ python -c "import os; os.chmod('somefile', 0o755)"

หาก Python ของคุณเก่ากว่า 2.6:

$ python -c "import os; os.chmod('somefile', 0755)"

12
รูปแบบ python3 ทำงานใน python 2.7.9 เช่นกัน ฉันไม่ได้ตรวจสอบเวอร์ชันก่อนหน้านี้
Fred Mitchell

3
ไวยากรณ์ Python 3 กลับไปใช้ Python 2.6 docs.python.org/3/whatsnew/…
Pete

ทำงานให้ฉันสิ!
LandiLeite

ควรจะเป็น00755เพียงเพื่อให้ชัดเจนว่าบิต suid / sgid / sticky ไปที่ใดในกรณีที่ผู้พัฒนาในภายหลังบางคนเข้ามาและต้องการให้สคริปต์เก่านี้ใช้เช่น sgid ด้วย2755แต่ก็ไม่สามารถหาสาเหตุได้ perms ถูกทำให้เมาอย่างสมบูรณ์ ;)
dannysauer

10

ชั้นนำ0หมายความว่านี่คือค่าคงที่ฐานแปดไม่ใช่ทศนิยม และคุณต้องมีฐานแปดเพื่อเปลี่ยนโหมดไฟล์

สิทธิ์เป็นรูปแบบบิตเช่นrwxrwx---อยู่111111000ในไบนารีและง่ายมากที่จะจัดกลุ่มบิตด้วย 3 เพื่อแปลงเป็นฐานแปดมากกว่าคำนวณการแทนทศนิยม

0644(ฐานแปด) เป็น0.110.100.100เลขฐานสอง (ฉันได้เพิ่มจุดเพื่อให้อ่านง่าย) หรือตามที่คุณคำนวณเป็น420ทศนิยม


5

ใช้สัญลักษณ์สิทธิ์แทนตัวเลข

ปัญหาของคุณจะหลีกเลี่ยงได้หากคุณใช้สัญลักษณ์อนุญาตที่มีชื่อตามความหมายมากกว่าตัวเลขเวทย์มนตร์ดิบเช่นสำหรับ664:

#!/usr/bin/env python3

import os
import stat

os.chmod(
    'myfile',
    stat.S_IRUSR |
    stat.S_IWUSR |
    stat.S_IRGRP |
    stat.S_IWGRP |
    stat.S_IROTH
)

นี้เป็นเอกสารที่https://docs.python.org/3/library/os.html#os.chmodและชื่อเป็นเช่นเดียวกับAPI POSIX Cman 2 statค่าเอกสารที่

ข้อดีอีกประการหนึ่งคือการพกพาที่มากขึ้นตามที่ระบุไว้ในเอกสาร:

หมายเหตุ: แม้ว่า Windows จะรองรับchmod()แต่คุณสามารถตั้งค่าแฟล็กแบบอ่านอย่างเดียวของไฟล์ได้เท่านั้น (ผ่านค่าคงที่stat.S_IWRITEและstat.S_IREADหรือค่าจำนวนเต็มที่เกี่ยวข้อง) บิตอื่น ๆ ทั้งหมดจะถูกละเว้น

chmod +xแสดงอยู่ที่: คุณทำ "chmod + x" ง่ายๆจากภายใน python ได้อย่างไร?

ทดสอบใน Ubuntu 16.04, Python 3.5.2


1
นี่คือวิธีจัดการกับปัญหาที่ถูกต้อง
carthurs

ฉันรู้ว่าวิธีนี้เป็นวิธีหลาม แต่แทบจะไม่น่า
เกลียด

2

หากคุณต้องการบันทึกสิทธิ์ลงในสตริงให้ทำ

s = '660'
os.chmod(file_path, int(s, base=8))

0

การใช้ stat. * bit มาสก์ดูเหมือนจะเป็นวิธีที่พกพาง่ายและชัดเจนที่สุดสำหรับฉันในการทำเช่นนี้ แต่ในทางกลับกันฉันมักลืมว่าจะจัดการอย่างไรให้ดีที่สุด ดังนั้นนี่คือตัวอย่างของการปิดบังสิทธิ์ "กลุ่ม" และ "อื่น ๆ " และปล่อยให้สิทธิ์ "เจ้าของ" โดยไม่ถูกแตะต้อง การใช้ bitmasks และการลบเป็นรูปแบบที่มีประโยชน์

import os
import stat
def chmodme(pn):
    """Removes 'group' and 'other' perms. Doesn't touch 'owner' perms."""
    mode = os.stat(pn).st_mode
    mode -= (mode & (stat.S_IRWXG | stat.S_IRWXO))
    os.chmod(pn, mode)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.