os.system 経由で pushd [重複] 質問する

os.system 経由で pushd [重複] 質問する

私は crontab を使用して、Minecraft サーバーのメンテナンス スクリプトを実行しています。crontab が再起動スクリプトを使用しようとしない限り、ほとんどの場合は正常に動作します。再起動スクリプトを手動で実行する場合、問題は発生しません。パス名に関係していると思うので、Minecraft コマンドが常に Minecraft ディレクトリから実行されるようにしています。そのため、コマンドを pushd/popd で囲んでいます。

os.system("pushd /directory/path/here")
os.system("command to sent to minecraft")
os.system("popd")

以下は、Minecraft を除いた対話型セッションです。単純な「ls」テストです。ご覧のとおり、os.system コマンドは pushd ディレクトリからではなく、私の論点を説明するために Python を実行していたディレクトリである /etc/ から実行されます。明らかに pushd は Python 経由では動作しないので、他にこれを実現する方法がないかと考えています。ありがとうございます!

>>> def test():
...     import os
...     os.system("pushd /home/[path_goes_here]/minecraft")
...     os.system("ls")
...     os.system("popd")
... 
>>> test()
~/minecraft /etc
DIR_COLORS    cron.weekly  gcrypt         inputrc    localtime   mime.types         ntp       ppp         rc3.d       sasldb2         smrsh      vsftpd.ftpusers
DIR_COLORS.xterm  crontab      gpm-root.conf      iproute2   login.defs  mke2fs.conf            ntp.conf      printcap        rc4.d       screenrc        snmp       vsftpd.tpsave
X11       csh.cshrc    group          issue      logrotate.conf  modprobe.d         odbc.ini      profile         rc5.d       scsi_id.config  squirrelmail   vz
adjtime       csh.login    group-         issue.net  logrotate.d     motd               odbcinst.ini  profile.d       rc6.d       securetty       ssh        warnquota.conf
aliases       cyrus.conf   host.conf      java       lvm         mtab               openldap      protocols       redhat-release  security        stunnel        webalizer.conf
alsa          dbus-1       hosts          jvm        lynx-site.cfg   multipath.conf         opt       quotagrpadmins  resolv.conf     selinux         sudoers        wgetrc
alternatives      default      hosts.allow    jvm-commmon    lynx.cfg    my.cnf             pam.d         quotatab        rndc.key        sensors.conf    sysconfig      xinetd.conf
bashrc        depmod.d     hosts.deny     jwhois.conf    mail        named.caching-nameserver.conf  passwd        rc          rpc         services        sysctl.conf    xinetd.d
blkid         dev.d        httpd          krb5.conf  mail.rc     named.conf         passwd-       rc.d        rpm         sestatus.conf   termcap        yum
cron.d        environment  imapd.conf     ld.so.cache    mailcap     named.rfc1912.zones        pear.conf     rc.local        rsyslog.conf    setuptool.d     udev       yum.conf
cron.daily    exports      imapd.conf.tpsave  ld.so.conf     mailman     netplug            php.d         rc.sysinit      rwtab       shadow          updatedb.conf  yum.repos.d
cron.deny     filesystems  init.d         ld.so.conf.d   makedev.d   netplug.d          php.ini       rc0.d       rwtab.d         shadow-         vimrc
cron.hourly   fonts        initlog.conf   libaudit.conf  man.config  nscd.conf          pki       rc1.d       samba       shells          virc
cron.monthly      fstab        inittab        libuser.conf   maven       nsswitch.conf          postfix       rc2.d       sasl2       skel        vsftpd
sh: line 0: popd: directory stack empty

=== (Python 2.4 を搭載した CentOS サーバー)

ベストアンサー1

Python 2.5 以降では、次のようにコンテキスト マネージャーを使用する方がよいと思います。

import contextlib
import os


@contextlib.contextmanager
def pushd(new_dir):
    previous_dir = os.getcwd()
    os.chdir(new_dir)
    try:
        yield
    finally:
        os.chdir(previous_dir)

次のように使用できます。

with pushd('somewhere'):
    print os.getcwd() # "somewhere"

print os.getcwd() # "wherever you started"

コンテキスト マネージャーを使用すると、例外と戻り値が安全になります。コンテキスト ブロック内から例外をスローしたり戻ったりした場合でも、コードは常に開始した場所に戻ります。

グローバル ディレクトリ スタックに依存せずに、ネストされたブロック内に pushd 呼び出しをネストすることもできます。

with pushd('somewhere'):
    # do something
    with pushd('another/place'):
        # do something else
    # do something back in "somewhere"

おすすめ記事