วิธีการตั้งค่าตัวแปรสภาพแวดล้อมใน Python


658

ฉันต้องการตั้งค่าตัวแปรสภาพแวดล้อมบางอย่างในสคริปต์ python และฉันต้องการสคริปต์อื่นทั้งหมดที่ถูกเรียกจาก python เพื่อดูชุดตัวแปรสภาพแวดล้อม

ถ้าฉันทำ

os.environ["DEBUSSY"] = 1`

มันบ่นบอกว่า1จะต้องมีสตริง

ฉันต้องการทราบวิธีการอ่านตัวแปรสภาพแวดล้อมใน python (ในส่วนหลังของสคริปต์) เมื่อฉันตั้งค่า



ยังเกี่ยวข้องกับ: youtu.be/ScyxIfOuSXs?t=61
Yannic Hamann

ไม่เกี่ยวข้องกับคำถาม: ฉันอ่านว่า ชื่อเป็นแมว
เหม็ด

คำตอบ:


790

ตัวแปรสภาพแวดล้อมต้องเป็นสตริงดังนั้นควรใช้

os.environ["DEBUSSY"] = "1"

การตั้งค่าตัวแปรสตริงDEBUSSY1

หากต้องการเข้าถึงตัวแปรนี้ในภายหลังเพียงใช้:

print(os.environ["DEBUSSY"])

กระบวนการลูกได้สืบทอดตัวแปรสภาพแวดล้อมของกระบวนการหลักโดยอัตโนมัติ - ไม่จำเป็นต้องดำเนินการใด ๆ เป็นพิเศษในส่วนของคุณ


20
ในบางแพลตฟอร์มการแก้ไข os.environ จะไม่แก้ไขสภาพแวดล้อมระบบจริงสำหรับกระบวนการปัจจุบันหรือกระบวนการลูก ดูเอกสารสำหรับข้อมูลเพิ่มเติม: docs.python.org/2/library/os.html#os.environ
Evan

8
@Evan อาจมี Unix หลากหลายในอดีตที่ไม่รองรับputenv()แต่สำหรับ Unixen นั้นไม่มีอะไรที่คุณสามารถทำได้ แม้แต่เวอร์ชันเก่าของ AIX และ HPUX ที่ฉันทำงานด้วยก็สนับสนุน หากใครสามารถค้นหาคอมพิวเตอร์ที่ไม่รองรับในวันนี้ฉันมีข้อสงสัยอย่างมากที่พวกเขาจะสามารถเรียกใช้ Python บนคอมพิวเตอร์เครื่องนั้นได้ :)
Sven Marnach

3
ข้อควรระวัง:เพื่ออ้างอิงจากการอ้างอิงของ @ Evan ข้างต้นการเปลี่ยนแปลงสภาพแวดล้อมดังกล่าวมีผลต่อกระบวนการย่อยที่เริ่มต้นด้วย os.system (), popen () หรือ fork () และ execv () กล่าวอีกนัยหนึ่งโปรดทราบว่าวิธีนี้จะไม่ปรับเปลี่ยนวิธีการทำงานของโปรแกรมของคุณเฉพาะวิธีที่ลูกของโปรแกรมของคุณทำงาน จริงโปรแกรมของคุณสามารถตั้งค่าและอ่านตัวแปรสภาพแวดล้อมได้ แต่จากสภาพแวดล้อมที่กำหนดค่าไว้สำหรับลูก ๆ ดูเพิ่มเติม: เปลี่ยนสภาพแวดล้อมกระบวนการปัจจุบัน จนถึงตอนนี้ฉันยังไม่พบวิธีที่สคริปต์ Python จะแก้ไข parent env
CODE-READ

1
@SvenMarnach เป็นคำสั่ง "กระบวนการเด็กโดยอัตโนมัติสืบทอดสภาพแวดล้อมของการปกครองจริงสำหรับเปลือกเช่นทุบตี.
กฤษณะ Oza

@darth_coder มันเป็นความจริงสำหรับทุกกระบวนการในระบบปฏิบัติการยูนิกซ์ ฉันไม่รู้เกี่ยวกับระบบปฏิบัติการอื่น โปรดทราบว่าตัวแปรเชลล์ไม่ได้เก็บไว้ในสภาพแวดล้อมเว้นแต่คุณจะส่งออก
Sven Marnach

114

คุณอาจต้องพิจารณาแง่มุมเพิ่มเติมสำหรับความทนทานของโค้ด

เมื่อคุณเก็บตัวแปรที่มีค่าจำนวนเต็มเป็นตัวแปรสภาพแวดล้อมให้ลอง

os.environ['DEBUSSY'] = str(myintvariable)

จากนั้นสำหรับการดึงข้อมูลให้พิจารณาว่าเพื่อหลีกเลี่ยงข้อผิดพลาดคุณควรลอง

os.environ.get('DEBUSSY', 'Not Set')

อาจแทนที่ '-1' สำหรับ 'Not Set'

ดังนั้นที่จะนำทั้งหมดเข้าด้วยกัน

myintvariable = 1
os.environ['DEBUSSY'] = str(myintvariable)
strauss = int(os.environ.get('STRAUSS', '-1'))
# NB KeyError <=> strauss = os.environ['STRAUSS']
debussy = int(os.environ.get('DEBUSSY', '-1'))

print "%s %u, %s %u" % ('Strauss', strauss, 'Debussy', debussy)

3
คุณบอกได้ไหมว่าจะตั้งค่าตัวแปรบนเครื่อง Linux ได้รหัสเดียวกันสำหรับแพลตฟอร์มทั้งหมดหรือไม่
Anurag-Sharma

2
มันไม่ค่อยสมเหตุสมผลที่จะเก็บ -1 สำหรับจำนวนเต็มที่ขาดหายไป ทางออกที่ดีกว่าจะเป็นmyvar = int(os.environ.get('MYVAR')) if os.environ.get('MYVAR', '') != '' else Noneเช่นนั้นจะไม่มีหากไม่มีหมายเลข
Benjamin Atkin

1
หากคุณกำลังจัดการกับจำนวนเต็ม -1 จะทำให้รู้สึก แม้ว่าฉันอาจจะตั้งค่าตัวแปร / ค่าคงที่เป็นค่าที่ฉันจะใช้สำหรับไม่ได้ตั้งค่า (เช่นvalue_not_set = '-1') จากนั้นคุณสามารถใช้debussy = int(os.environ.get('DEBUSSY', value_not_set))
yeOldeDataSmythe

68

os.environทำงานเหมือนพจนานุกรมไพ ธ อนดังนั้นการดำเนินการทั่วไปของพจนานุกรมสามารถทำได้ นอกเหนือจากgetและsetการดำเนินการที่กล่าวถึงในคำตอบอื่น ๆ เรายังสามารถตรวจสอบได้ว่ามีคีย์หรือไม่ คีย์และค่าที่ควรจะเก็บไว้เป็นสตริง

Python 3

สำหรับ python 3 พจนานุกรมใช้คีย์เวิร์ดinแทนhas_key

>>> import os
>>> 'HOME' in os.environ  # Check an existing env. variable
True
...

Python 2

>>> import os
>>> os.environ.has_key('HOME')  # Check an existing env. variable
True
>>> os.environ.has_key('FOO')   # Check for a non existing variable
False
>>> os.environ['FOO'] = '1'     # Set a new env. variable (String value)
>>> os.environ.has_key('FOO')
True
>>> os.environ.get('FOO')       # Retrieve the value
'1'

สิ่งสำคัญที่ควรทราบเกี่ยวกับการใช้os.environคือ:

แม้ว่ากระบวนการที่เด็กได้รับมรดกสิ่งแวดล้อมจากการปกครองที่ผมเคยทำงานเป็นปัญหาเมื่อเร็ว ๆ นี้และคิดว่าถ้าคุณมีสคริปต์อื่น ๆ การปรับปรุงสภาพแวดล้อมในขณะหลามสคริปต์ของคุณใช้เรียกos.environอีกครั้งจะไม่ได้สะท้อนให้เห็นถึงค่านิยมล่าสุด

ตัดตอนมาจากเอกสาร :

การจับคู่นี้ถูกจับในครั้งแรกที่นำเข้าโมดูลระบบปฏิบัติการโดยทั่วไปในระหว่างการเริ่มต้น Python ซึ่งเป็นส่วนหนึ่งของการประมวลผล site.py การเปลี่ยนแปลงสภาพแวดล้อมที่ทำหลังจากเวลานี้จะไม่ปรากฏในระบบปฏิบัติการยกเว้นการเปลี่ยนแปลงที่ทำโดยการปรับเปลี่ยนระบบปฏิบัติการโดยตรง

os.environ.data ซึ่งเก็บตัวแปรสภาพแวดล้อมทั้งหมดเป็นวัตถุ dict ซึ่งมีค่าสภาพแวดล้อมทั้งหมด:

>>> type(os.environ.data)  # changed to _data since v3.2 (refer comment below)
<type 'dict'>

1
ตัวแปรสภาพแวดล้อมของกระบวนการถูกตั้งค่าเมื่อกระบวนการถูกสร้างขึ้น การเปลี่ยนแปลงใด ๆ ที่ทำหลังจากนี้จะไม่มีผลกับสำเนาของตัวแปรสภาพแวดล้อมของกระบวนการ นี่เป็นเรื่องปกติของทุกกระบวนการไม่ใช่แค่งูใหญ่ นอกจากนี้os.environ.dataถูกเปลี่ยนชื่อใน Python 3.2 os.environ._dataเป็นคำนำหน้าขีดล่างซึ่งแสดงว่าคุณไม่ควรอ่านโดยตรง อย่างไรก็ตามos.environ._dataจะไม่มีค่าอัปเดตอยู่ดี
Al Sweigart

ใช่ฉันเข้าใจแล้ว ฉันต้องการแบ่งปันความประหลาดใจครั้งแรกกับคนอื่น ๆ ที่กำลังมองหา ขอขอบคุณที่ชี้การอัปเดตไปยังชื่อตัวแปรตั้งแต่ 3.2 จะอัปเดตคำตอบ
sisanared

21

ถ้าฉันทำ os.environ ["DEBUSSY"] = 1 มันบ่นว่า 1 จะต้องเป็นสตริง

จากนั้นทำ

os.environ["DEBUSSY"] = "1"

ฉันต้องการทราบวิธีการอ่านตัวแปรสภาพแวดล้อมใน python (ในส่วนหลังของสคริปต์) เมื่อฉันตั้งค่า

เพียงใช้os.environ["DEBUSSY"]เช่นเดียวกับใน

some_value = os.environ["DEBUSSY"]

19

การตั้งค่าตัวแปร:

วิธีการกำหนดรายการโดยใช้คีย์:

import os    
os.environ['DEBUSSY'] = '1'  #Environ Variable must be string not Int

เพื่อรับหรือตรวจสอบว่ามีอยู่หรือไม่

เนื่องจากos.environเป็นอินสแตนซ์ที่คุณสามารถลองใช้วิธีวัตถุ

วิธีที่ 1:

os.environ.get('DEBUSSY') # this is error free method if not will return None by default

จะได้รับ'1'เป็นค่าตอบแทน

วิธีที่ 2:

os.environ['DEBUSSY'] # will throw an key error if not found!

วิธีที่ 3:

'DEBUSSY' in os.environ  # will return Boolean True/False

วิธีที่ 4:

os.environ.has_key('DEBUSSY') #last 2 methods are Boolean Return so can use for conditional statements

16

คุณควรกำหนดค่าสตริงให้กับตัวแปรสภาพแวดล้อม

os.environ["DEBUSSY"] = "1"

หากคุณต้องการอ่านหรือพิมพ์ตัวแปรสภาพแวดล้อมเพียงใช้

print os.environ["DEBUSSY"]

การเปลี่ยนแปลงนี้จะมีผลเฉพาะสำหรับกระบวนการปัจจุบันที่ได้รับมอบหมายมันจะไม่เปลี่ยนค่าอย่างถาวร กระบวนการลูกจะสืบทอดสภาพแวดล้อมของกระบวนการหลักโดยอัตโนมัติ

ป้อนคำอธิบายรูปภาพที่นี่


5
"การเปลี่ยนแปลงนี้จะมีผลเฉพาะกับกระบวนการปัจจุบันที่ได้รับมอบหมายมันจะไม่เปลี่ยนค่าอย่างถาวร" นี่เป็นการตอบคำถามที่ฉันมีเกี่ยวกับขอบเขตของการตั้งค่าตัวแปรสภาพแวดล้อม
spitfiredd

2
ถ้าฉันออกจากเปลือกงูหลามและชุดระบบปฏิบัติการสภาพแวดล้อมก่อนหน้านี้จะหายไป
MeadowMuffins

ฉันจะตั้งค่าตัวแปรสภาพแวดล้อมใน windows ได้อย่างไร ฉันพยายามset [<name>=[<value>]]แต่มันทำเฉพาะสำหรับกระบวนการทำงานปัจจุบัน เมื่อฉันปิด cmd มันไม่มีอยู่และแม้ว่าจะเปิดโปรแกรมอื่น ๆ ก็มองไม่เห็นก็ตาม
Filip


14

ฉันพยายามเพิ่มตัวแปรสภาพแวดล้อม เป้าหมายของฉันคือการเก็บข้อมูลผู้ใช้บางส่วนไว้ในตัวแปรระบบเพื่อที่ฉันจะสามารถใช้ตัวแปรเหล่านั้นสำหรับการแก้ปัญหาในอนาคตเพื่อเป็นทางเลือกแทนไฟล์กำหนดค่า อย่างไรก็ตามวิธีการที่อธิบายในรหัสด้านล่างไม่ได้ช่วยฉันเลย

import os
os.environ["variable_1"] = "value_1"
os.environ["variable_2"] = "value_2"
# To Verify above code
os.environ.get("variable_1")
os.environ.get("variable_2")

บล็อกรหัสง่าย ๆ นี้ทำงานได้ดีอย่างไรก็ตามตัวแปรเหล่านี้มีอยู่ในกระบวนการที่เกี่ยวข้องเช่นที่คุณจะไม่พบพวกเขาในแท็บตัวแปรสภาพแวดล้อมของการตั้งค่าระบบ windows รหัสข้างบนสวยมากไม่ได้ตอบสนองวัตถุประสงค์ของฉัน ปัญหานี้จะกล่าวถึงที่นี่: ปัญหาการบันทึกตัวแปร

os.environ.putenv(key, value)

ความพยายามอีกครั้งที่ไม่สำเร็จ ดังนั้นในที่สุดฉันจัดการเพื่อบันทึกตัวแปรสำเร็จภายในสภาพแวดล้อมของหน้าต่างลงทะเบียนโดยการเลียนแบบคำสั่ง windows shell ที่อยู่ในคลาสระบบของแพ็คเกจระบบปฏิบัติการ รหัสต่อไปนี้อธิบายความพยายามที่ประสบความสำเร็จ

os.system("SETX {0} {1} /M".format(key, value))

ฉันหวังว่านี่จะเป็นประโยชน์สำหรับคุณบางคน


12

ควรสังเกตว่าถ้าคุณพยายามตั้งค่าตัวแปรสภาพแวดล้อมเป็นการประเมินผล bash จะไม่เก็บสิ่งที่คุณคาดหวัง ตัวอย่าง:

from os import environ

environ["JAVA_HOME"] = "$(/usr/libexec/java_home)"

นี้จะไม่ประเมินว่ามันจะอยู่ในเปลือกดังนั้นแทนที่จะได้รับเป็นเส้นทางที่คุณจะได้รับการแสดงออกที่แท้จริง/Library/Java/JavaVirtualMachines/jdk1.8.0_144.jdk/Contents/Home$(/usr/libexec/java_home)

ตรวจสอบให้แน่ใจว่าได้ประเมินมันก่อนตั้งค่าตัวแปรสภาพแวดล้อมเช่น

from os import environ
from subprocess import Popen, PIPE

bash_variable = "$(/usr/libexec/java_home)"
capture = Popen(f"echo {bash_variable}", stdout=PIPE, shell=True)
std_out, std_err = capture.communicate()
return_code = capture.returncode

if return_code == 0:
    evaluated_env = std_out.decode().strip()
    environ["JAVA_HOME"] = evaluated_env
else:
    print(f"Error: Unable to find environment variable {bash_variable}")

11

คุณสามารถใช้os.environพจนานุกรมเพื่อเข้าถึงตัวแปรสภาพแวดล้อมของคุณ

ตอนนี้ปัญหาที่ฉันมีคือถ้าฉันพยายามใช้os.systemเพื่อเรียกใช้แบตช์ไฟล์ที่ตั้งค่าตัวแปรสภาพแวดล้อมของคุณ (โดยใช้คำสั่ง SET ในไฟล์ **. bat *) มันจะไม่ตั้งค่าเหล่านั้นสำหรับสภาพแวดล้อมของหลาม (แต่สำหรับ กระบวนการลูกที่สร้างขึ้นด้วยos.systemฟังก์ชั่น) ในการรับตัวแปรที่ตั้งไว้ในสภาพแวดล้อมของหลามฉันใช้สคริปต์นี้

import re
import system
import os

def setEnvBat(batFilePath, verbose = False):
    SetEnvPattern = re.compile("set (\w+)(?:=)(.*)$", re.MULTILINE)
    SetEnvFile = open(batFilePath, "r")
    SetEnvText = SetEnvFile.read()
    SetEnvMatchList = re.findall(SetEnvPattern, SetEnvText)

    for SetEnvMatch in SetEnvMatchList:
        VarName=SetEnvMatch[0]
        VarValue=SetEnvMatch[1]
        if verbose:
            print "%s=%s"%(VarName,VarValue)
        os.environ[VarName]=VarValue

9

เมื่อคุณเล่นกับตัวแปรสภาพแวดล้อม (เพิ่ม / แก้ไข / ลบตัวแปร) แนวทางปฏิบัติที่ดีคือการกู้คืนสถานะก่อนหน้าเมื่อการทำงานเสร็จสมบูรณ์

คุณอาจต้องการสิ่งที่modified_environผู้จัดการบริบทอธิบายในคำถามนี้เพื่อกู้คืนตัวแปรสภาพแวดล้อม

การใช้คลาสสิก:

with modified_environ(DEBUSSY="1"):
    call_my_function()
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.