Вот краткое описание способов вызова внешних программ и преимуществ и недостатков каждого из них:
os.system("some_command with args")
передает команду и аргументы в оболочку вашей системы. Это хорошо, потому что вы можете запускать сразу несколько команд таким образом и настраивать каналы и перенаправление ввода / вывода. Например: os.system("some_command < input_file | another_command > output_file")
Однако, хотя это удобно, вы должны вручную обрабатывать экранирование символов оболочки, таких как пробелы и т. Д. С другой стороны, это также позволяет запускать команды, которые являются просто командами оболочки, а не фактически внешними программами , См. документацию . stream = os.popen("some_command with args")
будет делать то же самое, что и os.system
, за исключением того, что он дает файл-подобный объект, который вы можете использовать для доступа к стандартному вводу / выводу для этого процесса. Есть еще 3 варианта popen, которые все обрабатывают i / o немного по-другому. Если вы передаете все как строку, ваша команда передается в оболочку; если вы передадите их в список, то вам не нужно беспокоиться о том, чтобы избежать чего-либо. См. документацию . Popen
модуля subprocess
. Это предназначено для замены os.popen
, но имеет недостаток в том, что он немного усложняется благодаря тому, что он настолько всеобъемлющий. Например, вы могли бы сказать: print subprocess.Popen("echo Hello World", shell=True, stdout=subprocess.PIPE).stdout.read()
вместо: print os.popen("echo Hello World").read()
, но хорошо иметь все варианты там в одном унифицированном классе вместо 4 различных функций popen. См. документацию . call
из модуля subprocess
. Это в основном так же, как класс Popen
, и принимает все те же аргументы, но он просто ждет, пока команда не завершится, и вы получите код возврата. Например: return_code = subprocess.call("echo Hello World", shell=True)
См. документацию . subprocess.run
, что очень похоже на выше, но еще более гибкое и возвращает объект CompletedProcess
, когда команда завершает выполнение. Возможно, модуль subprocess
- это то, что вы используете.
Наконец, имейте в виду, что для всех методов, в которых вы передаете окончательную команду для выполнения оболочкой в виде строки, и вы несете ответственность за ее выход из нее. Имеются серьезные последствия для безопасности, если какая-либо часть передаваемой строки не может быть полностью доверена. Например, если пользователь вводит какую-либо / любую часть строки. Если вы не уверены, используйте эти методы только с константами. Чтобы дать вам намек на последствия, рассмотрите этот код:
print subprocess.Popen("echo %s " % user_input, stdout=PIPE).stdout.read()
и представьте, что пользователь вводит «моя мама не любила меня & amp; & amp; rm -rf /".
Как правило, вы можете использовать тип класса, а не тип enum. Перечисления должны быть статичными и окончательными. Идея конструктора enum заключается в том, чтобы инкапсулировать несколько значений, чтобы их можно было использовать после установки только одного типа enum.
public enum Vehicle {
CAR(4, 2),
TRUCK(6, 20);
private Integer numOfTyres;
private Integer maxWeight;
Vehicle(Integer numOfTyres, Integer maxWeight) {
this.numOfTyres = numOfTyres;
this.maxWeight = maxWeight;
System.out.println("Number of Tyres = " + numOfTyres);
System.out.println("Max weight = " + maxWeight);
}
public Integer getMaxWeight() {
return maxWeight;
}
public Integer getNumberOfTyres() {
return numOfTyres;
}
}
public class Main {
public static void main(String s[]) {
Vehicle.CAR.getNumberOfTyres();
for (Vehicle v : Vehicle.values()) {
System.out.println();
StringBuilder sb = new StringBuilder();
sb.append("Vehicle ");
sb.append(v.name());
sb.append(" has ");
sb.append(v.getNumberOfTyres());
sb.append(" number of tyres and ");
sb.append(v.getMaxWeight());
sb.append(" max weight ");
System.out.println("-----------------");
System.out.println(sb.toString());
System.out.println("-----------------");
}
}
}
Как вы, вероятно, знаете, конструктор для типа enum должен быть закрытым или закрытым доступом.
Он вызывается автоматически и создает константы, которые определены в начале тела enum.
Вы не можете вызвать конструктор enum самостоятельно.
Вот несколько примеров, которые могут быть полезны.
public enum MySingleton {
// if you have multiple constants here - it's not Singleton
INSTANCE;
// if you need to provide some info to your INSTANCE,
// you can add params to its methods
public void someMethod(String value) {
System.out.println("inside someMethod, value is " +value);
}
}
Если вам нужно, чтобы экземпляр имел некоторое состояние, вы можете добавить поля и конструктор:
public enum MySingleton {
INSTANCE("Hello");
private String message;
MySingleton(String msg) {
this.message = msg;
}
// you can even have getter/setter for it
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
Пример основного метода:
public static void main(String[] args) {
System.out.println(MySingleton.INSTANCE.getMessage()); // prints Hello
MySingleton.INSTANCE.setMessage("Bye");
System.out.println(MySingleton .INSTANCE.getMessage()); // prints Bye
}
У вас может быть что-то подобное
enum C1 {
WITH_PARAM("value"),
EMPTY();
private String value;
C1(String s) {
System.out.println("with param = " +s);
value=s;
}
C1() {
System.out.println("without param");
}
public void g() {
System.out.println("inside g, value is "+value);
}
}
public static void main(String s[]) {
C1.EMPTY.g();
C1.WITH_PARAM.g();
}
.