Başka bir komut dosyasından komut dosyasını çağırmanın en iyi yolu nedir?


307

Bir modülde olmayan test1.py adlı bir komut dosyası var. Sadece betiğin kendisi çalıştırıldığında çalıştırılması gereken bir kod vardır. Hiçbir işlevi, sınıfları, yöntemleri, vb vardır. Hizmet olarak çalışan başka bir komut dosyası var. Hizmet olarak çalışan komut dosyasından test1.py'yi çağırmak istiyorum.

Örneğin:

Test1.py dosyası

print "I am a test"
print "see! I do nothing productive."

Service.py dosyası

# Lots of stuff here
test1.py # do whatever is in test1.py

Dosyayı açan, içeriği okuyan ve temelde değerlendiren bir yöntemin farkındayım. Bunu yapmanın daha iyi bir yolu olduğunu varsayıyorum. Ya da en azından umarım.


42
Daha iyi yol yöntemleri ve sınıfları yazmak ve kullanmaktır
Aamir


3
runpy.run_moduleHenüz kimse bir cevap atmadı mı ?!
Aran-Fey

Yanıtlar:


279

Bunu yapmanın olağan yolu aşağıdaki gibidir.

test1.py

def some_func():
    print 'in test 1, unproductive'

if __name__ == '__main__':
    # test1.py executed as script
    # do something
    some_func()

service.py

import test1

def service_func():
    print 'service func'

if __name__ == '__main__':
    # service.py executed as script
    # do something
    service_func()
    test1.some_func()

44
test1.pyUzak bir dizinde bulunuyorsa ne olur ?
Evgeni Sergeev


18
Bu soruya gerçekten cevap vermiyor, değil mi? Komut dosyasının tamamını yürütmüyorsunuz, içe aktardığınız komut dosyasının içinden bazı işlevleri yürütüyorsunuz.
17'de

2
@GennaroTedesco: Yanılıyorsunuz. import test1İçinde service.pygerçekten çalıştırıyor bütün (sadece tanımlayan senaryoyu some_func()beri __name__ == '__main__'olacak Falsebu durumda). Bu, tüm OP'nin yapmak istediği gibi geliyor. Bu cevap bunun ötesine geçer, ama kesinlikle soruyu cevaplar - ve sonra bazıları.
martineau

2
Örneğin, test1.pyişlevin tanımını içermiyorsa some_func()(örneğin, yalnızca bazı kod satırları print("hello")), kodunuz çalışmazsa. Bu özel örnekte işe yarar çünkü esasen daha sonra geri çağırdığınız harici bir işlevi içe aktarırsınız.
gented

144

Bu, Python 2'de aşağıdakileri kullanarak mümkündür

execfile("test2.py")

Durumunuzda önemliyse ad alanlarının kullanımı ile ilgili belgelere bakın .

Python 3'te bu mümkündür (@fantastory sayesinde)

exec(open("test2.py").read())

Ancak, farklı bir yaklaşım kullanmayı düşünmelisiniz; senin fikrin (görebildiğim kadarıyla) çok temiz görünmüyor.


9
doğrudan ben python 32 İhtiyacım olan exec (açık ('test2.py'). read ())
fantezisi

8
Bu yaklaşım, çağrı yapan ad alanındaki komut dosyalarını yürütür. :)
dmvianna

6
komut satırı bağımsız değişkenlerini komut dosyasına geçirmek için sys.argvlisteyi düzenleyebilirsiniz .
jfs

1
Python 3 eşdeğerleri hakkında daha kapsamlı tedavi: stackoverflow.com/questions/436198/…
John Y

2
Bu, argümanları kabul etmez (PY dosyasına iletilecek)!
Apostolos

70

Diğer yol:

Test1.py dosyası:

print "test1.py"

Service.py dosyası:

import subprocess

subprocess.call("test1.py", shell=True)

Bu yöntemin avantajı, tüm kodunu bir alt rutine yerleştirmek için mevcut bir Python betiğini düzenlemeniz gerekmemesidir.

Belgeler: Python 2 , Python 3


7
Ben kullanmak zorunda subprocess.call("./test1.py", shell=True)çalışması için
asmaier

5
shell=TrueGerekli olmadıkça kullanmayın .
Piotr Dobrogost

2
@PiotrDobrogost - Hangi durumların gerekli olacağını belirleyebilir misiniz?
sancho.s ReinstateMonicaCellio

7
Geçerli dizinin PATH içinde olmadığı tipik bir Unix üzerinde çalışmaz. test1.pyçalıştırılabilir olmalı ve shebang satırına ( #!/usr/bin/env python) sahip olmalı ve tam yolu belirtmelisiniz veya yürütülebilir dosyayı kendiniz belirtmelisiniz: call([sys.executable, os.path.join(get_script_dir(), 'test1.py')])burada get_script_dir()tanımlanmıştır .
jfs

5
Veya subprocess.call(['python', 'test1.py']).
Büyük McLargeHuge

21

Test1.py dosyasının service.py içinde çağrıldığı işlevle aynı işlevde kalmasını istiyorsanız, şöyle bir şey yapın:

test1.py

def main():
    print "I am a test"
    print "see! I do nothing productive."

if __name__ == "__main__":
    main()

service.py

import test1
# lots of stuff here
test1.main() # do whatever is in test1.py

3
Çalışma zamanı parametreleriniz varsa ne olur?
Gabriel Fuarı

13
import os

os.system("python myOtherScript.py arg1 arg2 arg3")  

Os'u kullanarak doğrudan terminalinizi arayabilirsiniz. Daha da spesifik olmak istiyorsanız, giriş dizenizi yerel değişkenlerle birleştirebilirsiniz, örn.

command = 'python myOtherScript.py ' + sys.argv[1] + ' ' + sys.argv[2]
os.system(command)

çağrıları os.systemkaçınılmalıdır, aynı herhangi bir Sınıf ile yapabilirsinizPopen, Call,
user1767754

Gönderen Python belgelerinde : altişlem modülü yeni süreçleri yumurtlama ve onların sonuçlarını almak için, daha güçlü olanaklar sağlar; bu modülü kullanmak bu işlevi kullanmak için tercih edilir.
Büyük McLargeHuge

12

Bunu yapmamalısın. Bunun yerine şunları yapın:

test1.py:

 def print_test():
      print "I am a test"
      print "see! I do nothing productive."

service.py

#near the top
from test1 import print_test
#lots of stuff here
print_test()

1
test1'i içe aktardığınızda dosyanın nerede olduğunu nasıl bilebilir? aynı dizinde olması gerekiyor mu? ne değilse?
NULL.Dude

8

Kullanım import test11 kullanım için - bu senaryoyu çalıştırır. Daha sonraki çağrılar için komut dosyasına içe aktarılan bir modül gibi davranın ve reload(test1)yöntemi çağırın .

Ne zaman reload(module)yürütülür:

  • Python modüllerinin kodu yeniden derlenir ve modül düzeyindeki kod yeniden verilir, böylece modül sözlüğündeki isimlere bağlı yeni bir nesne kümesi tanımlanır. Genişletme modüllerinin başlatma işlevi çağrılmaz

sys.modulesUygun eylemi başlatmak için basit bir kontrolü kullanılabilir. Komut dosyası adına dize ( 'test1') olarak başvurmaya devam etmek için ' import ()' yerleşimini kullanın.

import sys
if sys.modules.has_key['test1']:
    reload(sys.modules['test1'])
else:
    __import__('test1')

3
reloadPython 3'te geçti.
Piotr Dobrogost

1
bir modülün içe aktarılması, onu çalıştırmakla eşdeğer değildir, örneğin if __name__ == "__main__":korumayı düşünün . Başka daha ince farklılıklar olabilir. Global düzeyde rastgele kod bırakmayın. Bir işleve koyun ve içe aktarma işleminden sonra kabul cevap yerine
jfs

5

Runpy'ı tercih ederim :

#!/usr/bin/env python
# coding: utf-8

import runpy

runpy.run_path(path_name='script-01.py')
runpy.run_path(path_name='script-02.py')
runpy.run_path(path_name='script-03.py')

3

Neden sadece test1'i içe aktarmıyorsunuz? Her python betiği bir modüldür. Daha iyi bir yol, örn. Main / run test1.py, import test1 ve run test1.main () işlevine sahip olmaktır. Veya test1.py dosyasını bir alt işlem olarak yürütebilirsiniz.


3

Daha önce de belirtildiği gibi, runpy mevcut komut dosyasından diğer komut dosyalarını veya modülleri çalıştırmak için iyi bir yoldur.

Bu arada, bir izleyici veya hata ayıklayıcının bunu yapması oldukça yaygındır ve bu gibi durumlarda dosyayı doğrudan içe aktarma veya bir alt işlemde çalıştırma gibi yöntemler genellikle çalışmaz.

execKodu çalıştırmak için de dikkat edilmesi gerekir . run_globalsİçe aktarma hatasını veya diğer bazı sorunları önlemek için uygun bir şekilde sağlamanız gerekir . Ayrıntılar runpy._run_codeiçin bakın.


0

Bu subprocesskütüphane ile bir örnektir :

import subprocess

python_version = '3'
path_to_run = './'
py_name = '__main__.py'

# args = [f"python{python_version}", f"{path_to_run}{py_name}"]  # Avaible in python3
args = ["python{}".format(python_version), "{}{}".format(path_to_run, py_name)]

res = subprocess.Popen(args, stdout=subprocess.PIPE)
output, error_ = res.communicate()

if not error_:
    print(output)
else:
    print(error_)

1
Python'u Python'un bir alt süreci olarak çalıştırmak neredeyse hiçbir zaman doğru çözüm değildir. Bir alt işlemle devam ederseniz Popen, üst düzey işlevler gerçekten istediğinizi yapamazsa kaçınmalısınız . Bu durumda check_callveya runihtiyacınız olan her şeyi ve daha fazlasını kendi kodunuzda önemli ölçüde daha az sıhhi tesisatla yapacaksınız.
üçlü

0

Bu süreç bir şekilde ortodoks değildir, ancak tüm python sürümlerinde çalışır,

Bir 'if' koşulu içinde 'recommend.py' adlı bir komut dosyası yürütmek istediğinizi varsayalım,

if condition:
       import recommend

Teknik farklı, ama işe yarıyor!

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.