Как использовать подпроцесс, когда несколько аргументов содержат пробелы?

Если реализации Bar.doesStuff и Baz.doesStuff ведут себя по-разному, подходящим решением является наличие двух отдельных тестов.

import org.scalatest.FlatSpec

class FooSpec1 extends FlatSpec {

  "a Bar" should "do a bar thing" in {
    Bar().doesStuff() == 42
  }

  "a Baz" should "do a baz thing" in {
    Baz().doesStuff() % 2 == 0
  }

}

Однако, если они имеют одинаковое поведение, вы можете изменить рефакторинг тестов с помощью функции, чтобы избежать дублирования кода. Я не верю, что scalatest может достичь этого шаблона повторного использования на уровне спецификации, как вы и просили.

import org.scalatest.FlatSpec

class FooSpec2 extends FlatSpec {

  def checkDoesStuff(foo: Foo): Boolean =
    foo.doesStuff() == 42

  "a Bar" should "do a bar thing" in {
    checkDoesStuff(Bar())
  }

  "a Baz" should "do a baz thing" in {
    checkDoesStuff(Baz())
  }

}

Тем не менее, тестирование на основе свойств может сделать именно то, что вы ищете. Вот пример использования scalacheck:

import org.scalacheck.{Gen, Properties}
import org.scalacheck.Prop.forAll

object FooProperties extends Properties("Foo"){

  val fooGen: Gen[Foo] = Gen.pick(1, List(Bar(), Baz())).map(_.head)

  property("a Foo always does stuff") = forAll(fooGen){
    (foo: Foo) => foo.doesStuff() == 42
  }

}

В отличие от спецификаций ScalaTest, свойства всегда являются функциями. Функция forAll берет генератор, выбирает значения генератора и запускает тест на всех выборках. Наш генератор всегда будет возвращать экземпляр Bar или Baz, что означает, что свойство будет охватывать все случаи, которые вы хотите проверить. forAll утверждает, что если один тест не пройден, все свойство не будет выполнено.

21
задан 30 April 2009 в 01:17
поделиться

9 ответов

'c:\Program' is not recognized as an internal or external command,
operable program or batch file.

Чтобы получить это сообщение, вы можете:

  1. Использовать shell = True :

     vmrun_cmd = r "c: \ Program Files \ VMware \ VMware Server \ VMware-cmd.bat»
    subprocess.Popen (vmrun_cmd, shell = True)
    
  2. Изменение vmrun_cmd в другой части вашего кода

  3. Получение этой ошибки из чего-то внутри vmware-cmd.bat

Попытка:

  • Откройте приглашение python и выполните следующую команду:

     subprocess. Popen ([r "c: \ Program Files \ VMware \ VMware Server \ vmware-cmd.bat"])
    

Если это работает, то о проблемах цитирования не может быть и речи. Если нет, то вы изолировали проблему.

5
ответ дан 29 November 2019 в 22:14
поделиться

В Python в MS Windows класс subprocess.Popen использует API CreateProcess для запуска процесса. CreateProcess принимает строку, а не что-то вроде массива аргументов. Python использует subprocess.list2cmdline для преобразования списка аргументов в строку для CreateProcess.

На вашем месте я бы посмотрел, что возвращает subprocess.list2cmdline (args) (где args - первый аргумент Popen). Было бы интересно посмотреть, ставит ли он кавычки вокруг первого аргумента.

Конечно, это объяснение может не применяться в среде Cygwin.

С учетом всего этого у меня нет MS Windows.

2
ответ дан 29 November 2019 в 22:14
поделиться

Я считаю, что list2cmdline (), который выполняет обработку из вашего списка аргументов, разделяет любые строковые аргументы в пробелах, если строка не содержит двойных кавычек. Поэтому я ожидаю, что

vmrun_cmd = r'"c:/Program Files/VMware/VMware Server/vmware-cmd.bat"'

будет тем, что вы хотите.

Вы также, вероятно, захотите заключить другие аргументы (например, target_vm ) в двойные кавычки, предполагая, что они тоже представляют каждый отличный аргумент для представления в командной строке. Подойдет что-то вроде

r'"%s"' % target_vm

(например).

См. документацию list2cmdline

D '

1
ответ дан 29 November 2019 в 22:14
поделиться

Почему вы используете r ""? Я считаю, что если вы удалите «r» с самого начала, он будет рассматриваться как стандартная строка, которая может содержать пробелы. Затем Python должен правильно заключать строку в кавычки при отправке в оболочку.

-2
ответ дан 29 November 2019 в 22:14
поделиться

Возможно, глупое предложение, но, возможно, попробуйте следующее, чтобы удалить подпроцесс + пробелы из уравнения:

import os
from subprocess Popen, PIPE

os.chdir(
    os.path.join("C:", "Program Files", "VMware", "VMware Server")
)

p = Popen(
    ["vmware-cmd.bat", target_vm, list_arg, list_arg2],
    stdout=PIPE
).communicate()[0]

Возможно, стоит попробовать.

p = Popen(
    [os.path.join("C:", "Program Files", "VMware", "VMware Server", "vmware-cmd.bat"), ...
-2
ответ дан 29 November 2019 в 22:14
поделиться

Here's what I don't like

vmrun_cmd = r"c:/Program Files/VMware/VMware Server/vmware-cmd.bat"

You've got spaces in the name of the command itself -- which is baffling your shell. Hence the "'c:\Program' is not recognized as an internal or external command, работоспособная программа или пакетный файл. "

Вариант 1 - поместите свой файл .BAT куда-нибудь еще. Действительно, поместите все свои VMWare в другое место. Вот правило: Не используйте каталог" Program Files "для чего-либо. Это просто неправильно.

Вариант 2 - процитировать значение vmrun_cmd

vmrun_cmd = r'"c:/Program Files/VMware/VMware Server/vmware-cmd.bat"'
-2
ответ дан 29 November 2019 в 22:14
поделиться

Если у вас есть пробелы в пути, я нашел самый простой способ правильно их интерпретировать:

subprocess.call('""' + path + '""')

Я не знаю, почему именно для этого нужны двойные двойные кавычки, но это то, что работает.

5
ответ дан 29 November 2019 в 22:14
поделиться

Одна проблема заключается в том, что если команда заключена в кавычки и не содержит пробелов, это также может сбить с толку оболочку.

Итак, я делаю следующее:

if ' ' in raw_cmd:
    fmt = '"%s"'
else:
    fmt = '%s'

cmd = fmt % raw_cmd
0
ответ дан 29 November 2019 в 22:14
поделиться
Другие вопросы по тегам:

Похожие вопросы: