সাবপ্রসেস ডিরেক্টরি পরিবর্তন করা হচ্ছে


98

আমি একটি উপ-ডিরেক্টরি / সুপার-ডিরেক্টরিতে (আমার প্রথমে এই সাব / সুপার ডিরেক্টরিতে থাকা প্রয়োজন) এর মধ্যে একটি স্ক্রিপ্ট সম্পাদন করতে চাই। আমি subprocessআমার উপ-ডিরেক্টরিতে প্রবেশ করতে পারি না :

tducin@localhost:~/Projekty/tests/ve$ python
Python 2.7.4 (default, Sep 26 2013, 03:20:26) 
[GCC 4.7.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import subprocess
>>> import os
>>> os.getcwd()
'/home/tducin/Projekty/tests/ve'
>>> subprocess.call(['cd ..'])
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.7/subprocess.py", line 524, in call
    return Popen(*popenargs, **kwargs).wait()
  File "/usr/lib/python2.7/subprocess.py", line 711, in __init__
    errread, errwrite)
  File "/usr/lib/python2.7/subprocess.py", line 1308, in _execute_child
    raise child_exception
OSError: [Errno 2] No such file or directory

পাইথন ওএসরর ফেলে দেয় এবং আমি জানি না কেন। আমি বিদ্যমান সাবডিরের মধ্যে যাওয়ার চেষ্টা করি বা একটি ডিরেক্টরি উপরে (উপরে হিসাবে) যাওয়ার চেষ্টা করি না - আমি সর্বদা একই ত্রুটিটি দিয়ে শেষ করি।


4
os.chdir()পরিবর্তে ব্যবহার করলে কী হয় ।
গ্রিওল

উত্তর:


152

আপনার কোড যা করার চেষ্টা করে তা হল একটি প্রোগ্রামকে কল করা cd ..। আপনি যা চান তা নামক কমান্ড কল করুন cd

তবে cdএটি একটি শেল অভ্যন্তরীণ। সুতরাং আপনি কেবল এটি হিসাবে কল করতে পারেন

subprocess.call('cd ..', shell=True) # pointless code! See text below.

তবে এটি করা অর্থহীন। যেহেতু কোনও প্রক্রিয়া অন্য প্রক্রিয়াটির কার্যকরী ডিরেক্টরি পরিবর্তন করতে পারে না (আবার, কমপক্ষে একটি ইউএনআইএক্স-এর মতো ওএসে, তবে উইন্ডোজেও), এই কলটি তার ডির পরিবর্তন করে তাৎক্ষণিকভাবে প্রস্থান করবে।

আপনি যা চান নামক প্যারামিটার দিয়ে os.chdir()বা যা অর্জন করতে পারে যা সাব-প্রসেস চালানোর আগে অবিলম্বে ওয়ার্কিং ডিরেক্টরি পরিবর্তন করে।subprocesscwd

উদাহরণস্বরূপ, lsরুট ডিরেক্টরিতে কার্যকর করতে, আপনি হয় করতে পারেন

wd = os.getcwd()
os.chdir("/")
subprocess.Popen("ls")
os.chdir(wd)

বা সহজভাবে

subprocess.Popen("ls", cwd="/")

4
cdসাধারণত বাইনারি হিসাবে উপস্থিত থাকে, কেবল শেল্ট অন্তর্নির্মিত নয়। ওপির আসল সমস্যাটি হ'ল তিনি বাইনারি বলছিলেন cd .., হ্যাঁ। (এবং আপনার তৃতীয় অনুচ্ছেদটি তার পরবর্তী সমস্যা হত, তাই ভাল উত্তর))
লিওন ওয়েবার

@ লিওন ওয়েবার কীভাবে cdবাইনারি হিসাবে কাজ করতে সক্ষম হওয়া উচিত ? এটি তার পিতামাতার কাজের দিরকে উচ্চারণ করতে পারে না।
glglgl

4
আমি লিনাক্স সম্পর্কে কথা বলছিলাম। যদিও ভাল পয়েন্ট। আমি নিজেকে হতাশ ছিল, এবং এখানে উত্তর আছে: /usr/bin/cdনিয়ে গঠিত builtin cd "$@"- তাই এটা শুধু শেল বিল্ট-ইন আহ্বান cdপাশাপাশি।
লিওন ওয়েবার

4
@ দ্য ডাইভার এজন্য cdঅবশ্যই অভ্যন্তরীণ শেল কমান্ড হিসাবে প্রয়োগ করতে হবে। এটি করার অন্য কোনও উপায় নেই। অভ্যন্তরীণ শেল কমান্ডগুলি শেলের মতো একই প্রক্রিয়াতে চালিত হয়। আমি কি subshell দ্বারা বোঝানো শেল জন্য মৃত্যুদন্ড কার্যকর করা হয় shell=True। এটি কার্যকর করার জন্য কমান্ড পায়, এটি কার্যকর করে এবং প্রস্থান করে।
glglgl

4
আমি মনে করি আপনার প্রস্তাবিত পদ্ধতির একটি বা দুটি উদাহরণ কার্যকর হবে।
স্কাইরাস

57

your_commandএকটি পৃথক ডিরেক্টরিতে সাবপ্রসেস হিসাবে চালাতে , @ উইমের উত্তরে প্রস্তাবিতcwd প্যারামিটারটি পাস করুন :

import subprocess

subprocess.check_call(['your_command', 'arg 1', 'arg 2'], cwd=working_dir)

একটি শিশু প্রক্রিয়া তার পিতামাতার কাজের ডিরেক্টরি পরিবর্তন করতে পারে না ( সাধারণত )। cd ..সাবপ্রসেস ব্যবহার করে চাইল্ড শেল প্রসেসে চালানো আপনার পিতামাত স্ক্রিপ্টের ওয়ার্কিং ডিরেক্টরিটি পরিবর্তন করবে না, যেমন @ গিগলগল এর উত্তরের কোড উদাহরণটি ভুলcdএটি একটি শেল অন্তর্নির্মিত (পৃথক নির্বাহযোগ্য নয়), এটি কেবল একই প্রক্রিয়াতে ডিরেক্টরি পরিবর্তন করতে পারে।


24

আপনি এক্সিকিউটেবলের জন্য একটি পরম পথ ব্যবহার করতে চান, এবং কার্য ডিরেক্টরিটি সেট করতে cwdকোয়ার্গ ব্যবহার করতে পারেন Popenদস্তাবেজগুলি দেখুন ।

সিডব্লিউডি যদি না হয় তবে বাচ্চার বর্তমান ডিরেক্টরিটি কার্যকর করার পূর্বে সিডব্লিউডে পরিবর্তন করা হবে। নোট করুন যে এক্সিকিউটেবল অনুসন্ধান করার সময় এই ডিরেক্টরিটি বিবেচনা করা হয় না, তাই আপনি সিডাব্লুডির সাথে সম্পর্কিত প্রোগ্রামটির পথ নির্দিষ্ট করতে পারবেন না।


এটি নির্ভর করে যদি অন্য সাব-প্রসেস কার্যকর করার কথা হয়। যদি তা হয় তবে আপনার পথটি সঠিক। তবে শুধুমাত্র নিজস্ব প্রোগ্রামটি ভিন্ন ডিরেক্টরিতে অভিনয় করার জন্য, এটি কোনও সহায়ক হবে না।
glglgl

আপনি কি বোঝাতে চাইছেন যে এটি সাহায্য করবে না? এটি করার একটি সুস্পষ্ট উপায় is
wim

4
না, এটি কেবল যে প্রক্রিয়াটি আমি চালু করতে যাচ্ছি তার সিডব্লিউডি পরিবর্তন করে যেমন subprocess.call(['ls', '-l'], cwd='/')। এই করতে cwd পরিবর্তন /এবং তারপর রান lsদিয়ে -lআর্গুমেন্ট হিসাবে। তবে আমি যদি করতে চাই os.chdir('/')এবং তারপরে open('etc/fstab', 'r'), আমি এটির os.chdir()সাথে কোনওরকম প্রতিস্থাপন করতে পারি না subprocess.XXX(cwd='/')কারণ এটি সাহায্য করবে না, যেমনটি বলা হয়েছিল। এটি দুটি সম্পূর্ণ ভিন্ন পরিস্থিতিতে।
glglgl

আমার উত্তরটি এক্সিকিউটেবলের জন্য একটি নিখুঁত পথ ব্যবহার করতে বলে কেন, আপনি কি সেই অংশটি মিস করেছেন?
wim

4
না, করিনি। আমার মনে হয় আমি হাল ছেড়ে দিয়েছি। আমি যদি বর্তমান চলমান ডিরেক্টরিটি পরিবর্তন করতে এবং একটি ফাইল খুলতে চাই তবে আমার কোনও এক্সিকিউটেবল নেই। এটি সম্পূর্ণ ভিন্ন পরিস্থিতি। বিটিডাব্লু: আমি যদি cwd=উদ্দেশ্য হিসাবে ব্যবহার করি তবে পরম পথ ব্যবহার করার দরকার নেই । আমি পাশাপাশি করতে পারি subprocess.call(['bin/ls', '-l'], cwd='/')
glglgl

18

subprocess.callsubprocessমডিউলটিতে এবং অন্যান্য পদ্ধতিগুলির একটি cwdপ্যারামিটার রয়েছে।

এই প্যারামিটারটি যেখানে আপনার প্রক্রিয়া চালাতে চান সেখানে কার্যনির্বাহী ডিরেক্টরি নির্ধারণ করে।

সুতরাং আপনি এর মতো কিছু করতে পারেন:

subprocess.call('ls', shell=True, cwd='path/to/wanted/dir/')

সাব-প্রসেস.পোপেন-কনস্ট্রাক্টর ডক্স পরীক্ষা করে দেখুন


7

এই উত্তরের উপর ভিত্তি করে অন্য একটি বিকল্প: https://stackoverflow.com/a/29269316/451710

এটি আপনাকে cdএকই প্রক্রিয়াতে একাধিক কমান্ড (উদাঃ ) সম্পাদন করতে দেয় ।

import subprocess

commands = '''
pwd
cd some-directory
pwd
cd another-directory
pwd
'''

process = subprocess.Popen('/bin/bash', stdin=subprocess.PIPE, stdout=subprocess.PIPE)
out, err = process.communicate(commands.encode('utf-8'))
print(out.decode('utf-8'))

4
এটি কেবল একটি চক্রাকার এবং অকার্যকর উপায়shell=True, executable='/bin/bash'
ট্রিপলি


0

আপনি যদি সিডি কার্যকারিতা রাখতে চান (শেল = সত্য ধরে নিচ্ছেন) এবং এখনও পাইথন স্ক্রিপ্টের ক্ষেত্রে ডিরেক্টরিটি পরিবর্তন করতে চান, এই কোডটি 'সিডি' কমান্ডগুলিকে কাজ করার অনুমতি দেবে।

import subprocess
import os

def cd(cmd):
    #cmd is expected to be something like "cd [place]"
    cmd = cmd + " && pwd" # add the pwd command to run after, this will get our directory after running cd
    p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) # run our new command
    out = p.stdout.read()
    err = p.stderr.read()
    # read our output
    if out != "":
        print(out)
        os.chdir(out[0:len(out) - 1]) # if we did get a directory, go to there while ignoring the newline 
    if err != "":
        print(err) # if that directory doesn't exist, bash/sh/whatever env will complain for us, so we can just use that
    return

-1

আপনার যদি ডিরেক্টরি পরিবর্তন করতে হয় তবে একটি কমান্ড চালান এবং স্ট্যান্ড আউটপুটও পাবেন:

import os
import logging as log
from subprocess import check_output, CalledProcessError, STDOUT
log.basicConfig(level=log.DEBUG)

def cmd_std_output(cd_dir_path, cmd):
    cmd_to_list = cmd.split(" ")
    try:
        if cd_dir_path:
            os.chdir(os.path.abspath(cd_dir_path))
        output = check_output(cmd_to_list, stderr=STDOUT).decode()
        return output
    except CalledProcessError as e:
        log.error('e: {}'.format(e))
def get_last_commit_cc_cluster():
    cd_dir_path = "/repos/cc_manager/cc_cluster"
    cmd = "git log --name-status HEAD^..HEAD --date=iso"
    result = cmd_std_output(cd_dir_path, cmd)
    return result

log.debug("Output: {}".format(get_last_commit_cc_cluster()))

Output: "commit 3b3daaaaaaaa2bb0fc4f1953af149fa3921e\nAuthor: user1<user1@email.com>\nDate:   2020-04-23 09:58:49 +0200\n\n

আপনি check_callখারাপভাবে পুনর্নবীকরণ করছেন ।
ট্রিপলি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.