โทร. /home/test.sh ในสคริปต์ python

Sep 11 2020

ฉันมีไฟล์ที่เรียกว่า. /home/test.sh(ช่องว่างระหว่างไฟล์แรก.และ/เป็นเจตนา) ซึ่งมีตัวแปรสภาพแวดล้อมบางอย่าง ฉันต้องการโหลดไฟล์นี้และเรียกใช้ไฟล์.py. หากฉันรันคำสั่งด้วยตนเองก่อนบนเซิร์ฟเวอร์ Linux จากนั้นเรียกใช้สคริปต์ python มันจะสร้างเอาต์พุตที่ต้องการ อย่างไรก็ตามฉันต้องการเรียกใช้. /home/test.shจากภายใน python เพื่อโหลดโปรไฟล์และเรียกใช้โค้ดที่เหลือ หากโปรไฟล์นี้ไม่ได้โหลดสคริปต์ python จะรันและให้ 0 เป็นเอาต์พุต

โทร

subprocess.call('. /home/test.sh',shell=True)

ทำงานได้ดี แต่ไม่ได้โหลดโปรไฟล์บนเทอร์มินัล Linux เพื่อรันโค้ด python และให้ผลลัพธ์ที่ต้องการ

มีใครช่วยได้บ้าง

คำตอบ

2 alani Sep 12 2020 at 05:10

ตัวแปรสภาพแวดล้อมไม่ได้รับการสืบทอดโดยตรงจากกระบวนการหลักซึ่งเป็นสาเหตุที่วิธีง่ายๆของคุณไม่ได้ผล

หากคุณกำลังพยายามรับตัวแปรสภาพแวดล้อมที่ตั้งค่าไว้ในของคุณtest.shสิ่งหนึ่งที่คุณสามารถทำได้คือใช้envใน sub-shell เพื่อเขียนลงใน stdout หลังจากจัดหาสคริปต์จากนั้นใน Python คุณสามารถแยกวิเคราะห์สิ่งเหล่านี้และ ตั้งไว้ในเครื่อง

โค้ดด้านล่างจะใช้งานได้หากtest.shไม่ได้เขียนเอาต์พุตใด ๆ เอง (ถ้าเป็นเช่นนั้นสิ่งที่คุณสามารถทำได้เพื่อหลีกเลี่ยงechoสตริงตัวคั่นหลังจากนั้นจะจัดหาสตริงและก่อนที่จะเรียกใช้envจากนั้นในโค้ด Python ให้ถอดสตริงตัวคั่นและทุกอย่างที่อยู่ข้างหน้าออก)

import subprocess
import os

p = subprocess.Popen(". /home/test.sh; env -0", shell=True, 
                     stdout=subprocess.PIPE,
                     stderr=subprocess.PIPE)

out, _ = p.communicate()

for varspec in out.decode().split("\x00")[:-1]:
    pos = varspec.index("=")
    name = varspec[:pos]
    value = varspec[pos + 1:]
    os.environ[name] = value

# just to test whether it works - output of the following should include
# the variables that were set
os.system("env")

นอกจากนี้ยังควรพิจารณาด้วยว่าหากสิ่งที่คุณต้องการทำคือตั้งค่าตัวแปรสภาพแวดล้อมบางอย่างทุกครั้งก่อนที่คุณจะเรียกใช้โค้ด python ตัวเลือกหนึ่งคือเพียงแค่ซอร์สของคุณtest.shจากตัวห่อเชลล์สคริปต์และอย่าพยายามตั้งค่าภายใน python เลย:

#!/bin/sh
. /home/test.sh
exec "/path/to/your/python/script $@"

จากนั้นเมื่อคุณต้องการเรียกใช้โค้ด Python ให้เรียกใช้ wrapper แทน